Funciones sobre cadenas de texto
Introducción
Las cadenas de texto (texto, string) pueden aparecer como parte de un protocolo de dispositivo, p. ej., como mensaje de error de un subsistema o de la transmisión de datos de medición a través de una interfaz serie. Muchos protocolos de comunicación basados en web también se construyen sobre cadenas de texto.
El módulo Math admite el tipo escalar string, que normalmente contiene caracteres codificados en UTF-8.
Todos los tipos de datos pueden convertirse al tipo string, p. ej., con str(), o a los tipos de destino correspondientes con los demás operadores de conversión (cast), siempre que no se produzcan errores de sintaxis.
Operadores sobre texto
Con el tipo de datos string se admiten los siguientes operadores:
-
todos los operadores de comparación, aplicándose el orden numérico de los caracteres ASCII: p. ej.,
'4' < 'A' < 'a' -
operador
+, concatena dos cadenass_connected = s1 + s2;consejostr(x)convierte cualquier tipo de datos en una representación de cadena, también objetos multidimensionales como vectores y matrices. Para tener más control sobre el formato puede resultar útil la funciónsFormat(f, ...).
Propiedades y funciones básicas
Longitud de una cadena de texto "sLength"
La longitud de una cadena s en bytes se calcula de la siguiente manera
l = sLength(s);
En la codificación UTF-8, con la codificación correspondiente, los caracteres especiales también pueden ocupar varios bytes. Esta función determina el número de bytes, no el número de caracteres (imprimibles).
Extracción de una subcadena como copia "sCopy"
Una subcadena r de la cadena s puede extraerse de la siguiente manera
r = sCopy(s, b); // Kopie der Zeichenkette s ab Position b
r = sCopy(s, b, c); // Kopie der Zeichenkette s ab Position b der Länge c
r = sCopy(s, BC); // BC ist ein Vektor der Länge 2, der b und c beinhaltet (Verhalten wie bei sCopy(s, b, c)
r = sCopy(s, BC, sel); // BC ist eine Matrix mit zwei Spalten, die zu b und c korrespondieren,
// wobei sel einen selektierenden Zeilenindex darstellt
La matriz BC es en muchos casos el resultado de funciones de búsqueda, p. ej., sFind(), que pueden devolver varias coincidencias en la cadena. Mediante el índice sel puede extraerse directamente la parte de texto correspondiente.
Ejemplo:
// 0 1 2 3
// 0123456789012345678901234567890123456789
geo = 'lat: 51.234567, lon: 12.3456789';
p6 = sFind(geo, 'lat:\s*([0-9.+-]+)', {subex: true});
// => p6 := [ [ 0,14] // refers to 'lat: 51.234567'
// , [ 5, 9]]; // refers to '51.234567'
lat = dbl(sCopy(geo, p6, 1));
// => lat := 51.234567;
Extracción del inicio y del final de la cadena "sLeft", "sRight"
El inicio b y el final e de longitud l de la cadena s pueden obtenerse como copia de la siguiente manera
b = sLeft(s,l);
e = sRight(s,l);
Eliminación de una subcadena "sErase"
Para obtener una copia de una cadena s de la que se ha eliminado una subcadena, puede utilizarse lo siguiente
r = sErase(s, b); // Kopie der Zeichenkette s ohne Zeichen ab Position b
r = sErase(s, b, c); // Kopie der Zeichenkette s ohne Zeichen ab Position b der Länge c
r = sErase(s, BC); // BC ist ein Vektor der Länge 2, der b und c beinhaltet (Verhalten wie bei sErase(s, b, c)
r = sErase(s, BC, sel); // BC ist eine Matrix mit zwei Spalten, die zu b und c korrespondieren,
// wobei sel einen selektierenden Zeilenindex darstellt
La matriz BC es en muchos casos el resultado de funciones de búsqueda, p. ej., sFind(), que pueden devolver varias coincidencias en la cadena. Mediante el índice sel puede eliminarse directamente la parte de texto correspondiente.
Inserción de una cadena "sInsert"
Para insertar una cadena t dentro de una cadena s en la posición b y devolver una copia r, puede utilizarse lo siguiente
r = sInsert(s, b, t);
Crear, formatear, leer, limpiar
Extracción de valores de una cadena "sScan" 1
Esta función extrae valores de una cadena s a partir de una cadena de formato f:
v = sScan(f, s);
La cadena de formato f contiene marcadores de posición de la forma %<x> (la letra tras % es arbitraria y no influye en el tipo del resultado), así como partes literales que sirven de separadores en la cadena de origen. Para cada marcador de posición se extrae la parte de texto situada entre los literales y se convierte automáticamente al tipo de datos adecuado.
// Einzelner Wert → Skalar
lat = sScan('lat: %v', zeile); // => 51.234 (dbl)
port = sScan('port=%d', konfig); // => 8080 (uint)
// Mehrere Werte gleichen Typs → Vektor
v = sScan('lat: %v, lon: %v', zeile); // => [51.234, 12.345] (dbl-Vektor)
// Gemischte Typen → zeilenweise als String, adressierbar mit sLine()
raw = sScan('name: %v, age: %v', s); // => "Alice\n30"
name = sLine(raw, 0); // => "Alice"
age = sLine(raw, 1); // => "30"
| Comportamiento | Descripción |
|---|---|
| Último marcador de posición sin literal de cierre | lee hasta el final de la cadena |
| Comillas alrededor de un valor | se eliminan automáticamente |
| Literal de la cadena de formato no encontrado | devuelve cErr |
| Ningún marcador de posición en la cadena de formato | devuelve cErr |
Formato de una cadena "sFormat"
Para representar con formato, como cadena r, una cadena f que contiene, p. ej., valores numéricos, puede utilizarse la siguiente función
r = sFormat(f, ...);
Aquí, f representa una cadena de formato del tipo de printf(), y para cada marcador de posición de la forma %[<width>][.<precision>]<type> debe indicarse un argumento correspondiente.
-
<width>: ancho de campo opcional para la salida, width < 0: alineado a la izquierda -
.<precision>: opcional para f/g/e, número de decimales o de cifras significativas -
<type>: los argumentos se convierten según el tipo de salida elegido. Por ello no se necesitan indicaciones de longitud adicionales para el tipo de datos.<type>Tipo de datos Salida b <bool>Salida de 'false' o 'true' d <int>Número entero con signo, base 10 u <uint>Número entero sin signo, base 10 x, X <uint>Número entero sin signo, base 16
cifrasA-Fen minúscula (x) o mayúscula (X)o <uint>Número entero sin signo, base 8 f <dbl>Número de coma flotante sin exponente de 10
Ejemplo: 1234.5678g <dbl>Número de coma flotante en representación optimizada
como f o e según el orden de magnitud del número.
Ejemplos: 1234.45678, 1.2345e9, 1.2345e-12e <dbl>Número de coma flotante con exponente de 10
Ejemplo: 1.2345678e3s <str>Texto c2 <uint>Carácter Unicode con este código, codificado en UTF-8
Ejemplo: 0xE4 → ä; código no válido → U+FFFD (�)
Ejemplo:
template = 'alt: %6.2f, lat: %.9f, lon: %.9f';
tx = sFormat(template, 140.4, 49.8765432, -3.14);
// tx := 'alt: 140.40, lat: 49.876543200, lon: -3.140000000';
Cadena a partir de códigos de carácter "mkString" 2
Un vector A de números enteros (int o uint) se lee como una secuencia de códigos de carácter y se convierte en una cadena s
s = mkString(A);
s = mkString(A, {encoding: 'windows-1252', keepNull: false, masking: auto});
Cada elemento de A es una unidad de código de la codificación encoding: un byte en UTF-8 y en las codificaciones de 8 bits, 16 bits en UTF-16 y un carácter (code point) en UTF-32. El resultado, como toda cadena, está codificado en UTF-8.
| Opción | Valor por defecto | Significado |
|---|---|---|
| encoding | 'UTF-8' | Nombre de la codificación, p. ej., 'UTF-8', 'ISO-8859-1', 'windows-1252', 'UTF-16', 'UTF-16BE', 'UTF-32'. Una codificación desconocida para el sistema provoca un error. |
| keepNull | false | false: la cadena termina en el primer carácter nulo. true: los caracteres nulos se conservan en la cadena. |
| masking | auto | auto: cada elemento se enmascara al ancho de una unidad de código (8, 16 o 21 bits); los bits de mayor peso se ignoran. off o 0: sin enmascaramiento; un elemento fuera del rango de valores provoca un error. (de 1 a 32): máscara de bits; lee bytes también en UTF-16 y UTF-32, cuyo orden queda determinado por el nombre de la codificación (p. ej., 'UTF-16BE'). |
'UTF-8', 'ISO-8859-1', 'windows-1252' y 'UTF-32' están siempre disponibles. Todas las demás codificaciones, incluida 'UTF-16', dependen de los componentes del sistema instalados en el dispositivo.
Si UTF-16 o UTF-32 se leen byte a byte (masking ), el nombre debería indicar el orden de los bytes, p. ej., 'UTF-16BE' o 'UTF-32LE'. Sin esta indicación y sin marca de orden de bytes (byte order mark), se aplica el orden de bytes del dispositivo.
Una secuencia de caracteres no válida se sustituye por el carácter de sustitución U+FFFD (�). Si A no es un vector de int o uint, el resultado es un error.
Ejemplo:
// versión de software, transmitida como caracteres individuales en cuatro canales
A_Str = [swVer_C1, swVer_C2, swVer_C3, swVer_C4];
s = mkString(A_Str); // p. ej. '1.04'
t = mkString([0x80, 0xE4], {encoding: 'windows-1252'}); // 'ۊ'
u = mkString([0x00, 0x41, 0x20, 0xAC], {encoding: 'UTF-16BE', masking: 8}); // 'A€'
Acceso al contenido de un recurso "sResource"
La función devuelve el contenido del recurso indicado como cadena constante (binaria).
resStr = sResource({@ref:'myResource'});
Según la configuración, el contenido del recurso puede contener no solo texto UTF-8 puro (p. ej., un archivo INI o un objeto JSON), sino también datos binarios, como arrays de tipo double, imágenes jpg, etc. En particular, los datos binarios solo deben ser procesados por funciones especiales adecuadas. Para la implementación de tales funciones, no dude en ponerse en contacto con nosotros.
Eliminación de espacios en blanco "sTrim"
Esta función elimina todos los espacios en blanco (whitespace) al principio y al final del argumento, como por ejemplo en
s_trimmed = sTrim(s);
Conversión a mayúsculas/minúsculas "sUpper", "sLower"
La conversión de una cadena en cuanto a mayúsculas y minúsculas se realiza mediante
s_uppercase = sUpper(s);
s_lowercase = sLower(s);
Simplificación "sSimplify" de cadenas
La función sSimplify() sustituye todas las apariciones múltiples de espacios en blanco (espacios, tabuladores, CR, LF, ...) por un único espacio.
s_simple = sSimplify(s);
Normalización "sNormalize" de cadenas
La función sNormalize() elimina las comillas correspondientes "..." o '...' al principio y al final de la cadena y sustituye todas las secuencias de ESCAPE \ por el código que designan.
s_normalized = sNormalize(s);
Buscar, encontrar y descomponer
Búsqueda de subcadenas "sFind"
La función de búsqueda sFind devuelve el índice r o una matriz con la posición y la longitud de las partes de texto encontradas del patrón p en la cadena s, y puede utilizarse de la siguiente manera
r1 = sFind(s, {...}); // Konfiguration des 'pattern' ist zwingend
r1 = sFind(s,p); // direkte Suche ab Stringbeginn
r2 = sFind(s,p,b); // direkte Suche ab Position b
// Optionales Konfigurationsobjekt für alle Varianten
rx = sFind(..., { pattern: <string>
, case: <bool>
, all: <bool>
, regex: <bool>
, subex: <bool>
});
Si no se encuentra ningún patrón, esta función devuelve -1.
Una matriz con los resultados de la búsqueda tiene la siguiente estructura:
Esta matriz puede pasarse directamente, junto con el número de fila del resultado individual, a las funciones sCopy() o sErase().
Un resultado individual puede procesarse con la función GetRow() o mediante la indicación directa de la indexación:
part4 = sCopy(s, rx, 3); // counting from zero
part4a = sCopy(s, rx[3,0], rx[3,1]); // equivalent
part4_sc = GetRow(rx, 3); // vector [s3, c3]
part4b = sCopy(s, part4_sc); // equivalent
| Propiedad | Valor | Descripción |
|---|---|---|
| pattern | <str> | Patrón de búsqueda constante, si no se utiliza el parámetro p. Es algo más eficiente en los modos regex, ya que la expresión no tiene que compilarse de nuevo cada vez. |
| case | <bool> | Búsqueda distinguiendo mayúsculas y minúsculas (def.: false, sin distinguir mayúsculas y minúsculas) |
| all | <bool> | Devuelve un vector con las posiciones iniciales y las longitudes de las partes de texto coincidentes, no en combinación con subex |
| regex | <bool> | Interpreta el patrón pattern o p como expresión regular; el resultado es una matriz con la posición y la longitud de las expresiones/subexpresiones encontradas |
| subex | <bool> | Devuelve la posición y la longitud de las partes de texto extraídas en una matriz de resultados, activa regex automáticamente |
Ejemplos
// 0 1 2 3
// 0123456789012345678901234567890123456789
str = 'Hello world and hello my dear friends!';
p0 = sFind(str, "dog");
// => p0 := -1; // not found, independant of selected modes
// my test with (p0 < 0) ? ... : ...
// or isMatrix(p0) ? ... : ... for 'all'- or 'regex'-modes
p1 = sFind(str, "hello");
// => p1 := 0;
p2 = sFind(str, "hello", {case: true});
// => p2 := 16; // first one is now skipped
p3 = sFind(str, "hello", {all: true});
// => p3 := [ [ 0, 5]
// , [16, 5]];
p4 = sFind(str, "(and|dear)", { regex: true, all: true});
// => p4 := [ [12, 3]
// , [25, 4]];
p5 = sFind(str, 'dear\s+(\w+)', { subex: true });
// => p5 := [ [25, 12] // first row is complete match
// , [30, 7]]; // then (...) extractions follow
dear= sCopy(str, p5, 1);
// => dear:= 'friends';
// 0 1 2 3
// 0123456789012345678901234567890123456789
geo = 'lat: 51.234567, lon: 12.3456789';
p6 = sFind(geo, 'lat:\s*([0-9.+-]+)', {subex: true});
// => p6 := [ [ 0,14]
// , [ 5, 9]];
lat = dbl(sCopy(geo, p6, 1));
// => lat := 51.234567;
Sustitución de subcadenas "sReplace"
Para sustituir (varias) cadenas t_k dentro de la cadena s por el texto correspondiente de cada s_k, puede utilizarse lo siguiente
r = sReplace(s,t_1,s_1, ..., t_N,s_N);
La sustitución se realiza de forma secuencial en el orden de los argumentos; los valores s_k se convierten implícitamente a una representación de texto. Para tener más control sobre la conversión puede utilizarse la función sFormat().
Ejemplo:
template = 'alt: <alt>, lat: <lat>, lon: <lon>';
tx = sReplace(template, '<alt>', 140.4, '<lat>', 49.8765432, '<lon>', -3.14);
// tx := 'alt: 140.400000, lat: 49.876543, lon: -3.140000';
Búsqueda de una combinación clave-valor "sGetKV" 1
Esta función busca la clave k en una cadena (bloque de texto) s y devuelve el valor correspondiente. La búsqueda no distingue entre mayúsculas y minúsculas.
v1 = sGetKV(s, k);
// Optionaler Konfigurationsblock
vx = sGetKV(..., { format: <enum>
, filter: <regex>
, index: <uint>
});
| Propiedad | Valor | Descripción |
|---|---|---|
| format | <enum> | Establece el formato del bloque de texto y define el filter estándar adecuado. Valores posibles: json (estándar), ini, xml_attr, xml_node |
| filter | <regex> | Sobrescribe el estándar del formato: expresión regular que captura, tras el nombre de la clave, el valor correspondiente como grupo de captura (...) |
| index | <uint> | Selecciona la N-ésima coincidencia (base 0, estándar: 0). Útil cuando una clave aparece varias veces, p. ej., en elementos XML repetidos. |
Si no se encuentra la clave (o el índice supera el número de coincidencias), la función devuelve cErr. Las comillas alrededor del valor encontrado se eliminan automáticamente.
Variantes de formato
| Formato | Separador | Ejemplo típico |
|---|---|---|
json (estándar) | : tras la comilla de cierre opcional | {"key": "value", "count": 3} |
ini | =, valor hasta el final de la línea | host=localhost\nport=8080 |
xml_attr | =, valor entre comillas | <device id="42" name="sensor"/> |
xml_node | etiqueta XML <key>…</key> | <voltage>3.3</voltage> |
Elementos anidados y repetidos
sGetKV no evalúa la profundidad de anidamiento. En objetos anidados (p. ej., {"outer": {"inner": 1}}), index:0 apunta a la clave exterior; una búsqueda dirigida a valores de niveles inferiores requiere una evaluación en dos pasos: primero extraer el valor de la clave exterior y, a continuación, aplicar de nuevo sGetKV sobre él.
Los elementos repetidos de la misma clave (p. ej., <val>10</val><val>20</val>) pueden seleccionarse con index.
Ejemplos
cfg = '{"name": "Alice", "count": 3}';
name = sGetKV(cfg, 'name'); // => "Alice"
cnt = sGetKV(cfg, 'count'); // => 3 (uint)
ini = 'host=localhost\nport=8080';
port = sGetKV(ini, 'port', {format:'ini'}); // => 8080 (uint)
xml = '<data><voltage>3.3</voltage></data>';
u = sGetKV(xml, 'voltage', {format:'xml_node'}); // => 3.3 (dbl)
// Zweites Vorkommen eines wiederholten XML-Elements
seq = '<data><val>10</val><val>20</val><val>30</val></data>';
v1 = sGetKV(seq, 'val', {format:'xml_node'}); // => 10
v2 = sGetKV(seq, 'val', {format:'xml_node', index:1}); // => 20
// Eigener Filter für abweichende Syntax (key => value; ...)
v = sGetKV(s, 'temp', {filter:'\s*=>\s*([^;]+)'});
División de cadenas "sSplit"
Para dividir una cadena en un carácter ch puede utilizarse la función sSplit. Esta devuelve una matriz de dos columnas con todas las posiciones iniciales y longitudes de las subcadenas correspondientes
r1 = sSplit(s, ch);
// Optionaler Konfigurationsblock
rx = sSplit(..., { trim: <bool>
});
pos = rx[0, 0];
len = rx[0, 1];
| Propiedad | Valor | Descripción |
|---|---|---|
| trim | <bool> | Elimina los espacios en blanco al principio y al final de los elementos |
Número de líneas dentro de una cadena "sLines"
El número de líneas de una cadena s puede determinarse de la siguiente manera
lines = sLines(s);
Se admiten todas las variantes de saltos de línea (LF, CRLF, LFCR, CR).
Extracción de una línea de una cadena multilínea "sLine"
Para extraer la i-ésima línea de una cadena s resulta adecuada la siguiente función
lineI = sLine(s,i);
// Optionales Konfigurationsobjekt
lineX = sLine(..., { trim: <bool>
});
| Propiedad | Valor | Descripción |
|---|---|---|
| trim | <bool> | Elimina los espacios en blanco al principio y al final de la línea |
Lectura de líneas completas "sGetline"
La función sGetline() une los distintos valores del canal de tipo cadena s y los almacena hasta que puede emitirse una línea completa. Esta se retira del búfer y, con el resto que queda, se continúa la acumulación.
Para obtener una línea completa a partir de un flujo de caracteres puede utilizarse lo siguiente
line1 = sGetline(s);
// Optionales Konfigurationsobjekt
lineX = sGetline(..., { trim: <bool>
, eoln: <str>
, timeout: off|<time>
});
| Propiedad | Valor | Descripción |
|---|---|---|
| trim | <bool> | La línea emitida se limpia además de espacios |
| eoln | <string> | Definición del final de línea |
| timeout | off/<time> | Tiempo en segundos tras el último fragmento hasta que se inserta un final de línea. off2 o 0: sin final de línea tras el vencimiento del tiempo (def.) |