Funzioni sulle stringhe
Introduzione
Le stringhe (testo, string) possono comparire come parte di un protocollo di dispositivo, ad es. come messaggio di errore di un sottosistema o nella trasmissione di dati di misura tramite un'interfaccia seriale. Anche molti protocolli di comunicazione basati sul web si fondano su stringhe.
Il modulo Math supporta il tipo scalare string, che tipicamente contiene caratteri codificati in UTF-8.
Tutti i tipi di dati possono essere convertiti nel tipo string, ad es. con str(), oppure nei rispettivi tipi di destinazione con gli altri operatori di cast, purché non si verifichino errori di sintassi.
Operatori sul testo
Con il tipo di dati string sono supportati i seguenti operatori:
-
tutti gli operatori di confronto, dove vale l'ordine numerico dei caratteri ASCII: ad es.
'4' < 'A' < 'a' -
operatore
+, concatena due stringhes_connected = s1 + s2;suggerimentostr(x)converte qualsiasi tipo di dati in una rappresentazione di stringa, anche oggetti multidimensionali come vettori e matrici. Per avere più controllo sulla formattazione può essere utile la funzionesFormat(f, ...).
Proprietà e funzioni di base
Lunghezza di una stringa "sLength"
La lunghezza di una stringa s in byte si calcola come segue
l = sLength(s);
Nella codifica UTF-8, con la relativa codifica, i caratteri speciali possono occupare anche più byte. Questa funzione determina il numero di byte, non il numero di caratteri (stampabili)!
Estrazione di una sottostringa come copia "sCopy"
Una sottostringa r della stringa s può essere estratta come segue
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 matrice BC è in molti casi il risultato di funzioni di ricerca, ad es. sFind(), che possono restituire più riscontri nella stringa. Tramite l'indice sel è possibile estrarre direttamente la corrispondente parte di testo.
Esempio:
// 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;
Estrazione dell'inizio e della fine della stringa "sLeft", "sRight"
L'inizio b e la fine e della stringa s, di lunghezza l, possono essere ottenuti come copia nel modo seguente
b = sLeft(s,l);
e = sRight(s,l);
Rimozione di una sottostringa "sErase"
Per ottenere una copia di una stringa s da cui è stata rimossa una sottostringa si può utilizzare quanto segue
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 matrice BC è in molti casi il risultato di funzioni di ricerca, ad es. sFind(), che possono restituire più riscontri nella stringa. Tramite l'indice sel è possibile rimuovere direttamente la corrispondente parte di testo.
Inserimento di una stringa "sInsert"
Per inserire una stringa t all'interno di una stringa s in corrispondenza della posizione b e restituire una copia r si può utilizzare quanto segue
r = sInsert(s, b, t);
Creare, formattare, leggere, ripulire
Estrazione di valori da una stringa "sScan" 1
Questa funzione estrae valori da una stringa s in base a una stringa di formato f:
v = sScan(f, s);
La stringa di formato f contiene segnaposto della forma %<x> (la lettera dopo % è arbitraria e non influisce sul tipo del risultato) e parti letterali che fungono da separatori nella stringa di origine. Per ogni segnaposto viene estratta la parte di testo compresa tra i letterali e convertita automaticamente nel tipo di dati appropriato.
// 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"
| Comportamento | Descrizione |
|---|---|
| Ultimo segnaposto senza letterale di chiusura | legge fino alla fine della stringa |
| Virgolette attorno a un valore | vengono rimosse automaticamente |
| Letterale della stringa di formato non trovato | restituisce cErr |
| Nessun segnaposto nella stringa di formato | restituisce cErr |
Formattazione di una stringa "sFormat"
Per rappresentare in forma formattata come stringa r una stringa f che contiene, ad es., valori numerici, si può utilizzare la funzione seguente
r = sFormat(f, ...);
Qui f rappresenta una stringa di formato del tipo printf() e per ogni segnaposto deve essere indicato un argomento corrispondente della forma %[<width>][.<precision>]<type>.
-
<width>: larghezza di campo opzionale per l'output, width < 0: allineato a sinistra -
.<precision>: opzionale per f/g/e, numero di cifre decimali o di cifre significative -
<type>: gli argomenti vengono convertiti in base al tipo di output scelto. Indicazioni aggiuntive sulla lunghezza del tipo di dati non sono quindi necessarie.<type>Tipo di dati Output b <bool>Output di 'false' o 'true' d <int>Numero intero con segno, base 10 u <uint>Numero intero senza segno, base 10 x, X <uint>Numero intero senza segno, base 16
cifreA-Fminuscole (x) o maiuscole (X)o <uint>Numero intero senza segno, base 8 f <dbl>Numero in virgola mobile senza esponente in base 10
Esempio: 1234.5678g <dbl>Numero in virgola mobile in rappresentazione ottimizzata
come f o e a seconda dell'ordine di grandezza del numero.
Esempi: 1234.45678, 1.2345e9, 1.2345e-12e <dbl>Numero in virgola mobile con esponente in base 10
Esempio: 1.2345678e3s <str>Testo
Esempio:
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';
Accesso al contenuto di una risorsa "sResource"
La funzione restituisce il contenuto della risorsa indicata come stringa costante (binaria).
resStr = sResource({@ref:'myResource'});
A seconda della configurazione, il contenuto della risorsa può comprendere non solo puro testo UTF-8 (ad es. un file INI o un oggetto JSON), ma anche dati binari, come array double, immagini jpg, ecc. In particolare i dati binari possono essere elaborati ulteriormente solo da apposite funzioni speciali. Per l'implementazione di tali funzioni, siamo a vostra disposizione.
Rimozione degli spazi bianchi "sTrim"
Questa funzione rimuove tutti gli spazi bianchi (whitespace) all'inizio e alla fine dell'argomento, come ad es. in
s_trimmed = sTrim(s);
Conversione in maiuscolo/minuscolo "sUpper", "sLower"
La conversione di una stringa in maiuscolo o minuscolo avviene mediante
s_uppercase = sUpper(s);
s_lowercase = sLower(s);
Semplificazione "sSimplify" delle stringhe
La funzione sSimplify() sostituisce tutte le occorrenze multiple di spazi bianchi (spazi, tabulazioni, CR, LF, ...) con un singolo spazio.
s_simple = sSimplify(s);
Normalizzazione "sNormalize" delle stringhe
La funzione sNormalize() rimuove le virgolette corrispondenti "..." o '...' all'inizio e alla fine della stringa e sostituisce tutte le sequenze di ESCAPE \ con il codice indicato.
s_normalized = sNormalize(s);
Cercare, trovare e scomporre
Ricerca di sottostringhe "sFind"
La funzione di ricerca sFind restituisce l'indice r oppure una matrice con posizione e lunghezza delle parti di testo trovate del modello p nella stringa s e può essere utilizzata come segue
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>
});
Se non viene trovato alcun modello, questa funzione restituisce -1.
Una matrice con i risultati della ricerca ha la struttura seguente:
Questa matrice può essere passata direttamente, insieme al numero di riga del singolo risultato, alle funzioni sCopy() o sErase().
Un singolo risultato può essere elaborato ulteriormente con la funzione GetRow() oppure indicando direttamente l'indicizzazione:
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
| Proprietà | Valore | Descrizione |
|---|---|---|
| pattern | <str> | Modello di ricerca costante, se il parametro p non viene utilizzato. È un po' più performante per le modalità regex, perché l'espressione non deve essere tradotta ogni volta da capo. |
| case | <bool> | Ricerca con distinzione tra maiuscole e minuscole, (def: false, case insensitive) |
| all | <bool> | Restituisce un vettore con le posizioni iniziali e le lunghezze delle parti di testo corrispondenti, non in combinazione con subex |
| regex | <bool> | Interpreta il modello pattern o p come espressione regolare, il risultato è una matrice con posizione e lunghezza delle espressioni/sottoespressioni trovate |
| subex | <bool> | Restituisce posizione e lunghezza delle parti di testo estratte in una matrice di risultati, imposta automaticamente regex |
Esempi
// 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;
Sostituzione di sottostringhe "sReplace"
Per sostituire (più) stringhe t_k all'interno della stringa s con i rispettivi testi corrispondenti s_k si può utilizzare quanto segue
r = sReplace(s,t_1,s_1, ..., t_N,s_N);
La sostituzione avviene in modo sequenziale nell'ordine degli argomenti; i valori s_k vengono convertiti implicitamente in una rappresentazione testuale. Per avere più controllo sulla conversione si può utilizzare la funzione sFormat().
Esempio:
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';
Ricerca di una combinazione chiave-valore "sGetKV" 1
Questa funzione cerca la chiave k in una stringa (blocco di testo) s e restituisce il valore corrispondente. La ricerca non distingue tra maiuscole e minuscole.
v1 = sGetKV(s, k);
// Optionaler Konfigurationsblock
vx = sGetKV(..., { format: <enum>
, filter: <regex>
, index: <uint>
});
| Proprietà | Valore | Descrizione |
|---|---|---|
| format | <enum> | Definisce il formato del blocco di testo e imposta il filter standard appropriato. Valori possibili: json (predefinito), ini, xml_attr, xml_node |
| filter | <regex> | Sovrascrive il valore predefinito del formato: espressione regolare che — dopo il nome della chiave — cattura il valore corrispondente come gruppo di cattura (...) |
| index | <uint> | Seleziona l'N-esimo riscontro (a base 0, predefinito: 0). Utile quando una chiave compare più volte, ad es. con elementi XML ripetuti. |
Se la chiave non viene trovata (o l'indice supera il numero di riscontri), la funzione restituisce cErr. Le virgolette attorno al valore trovato vengono rimosse automaticamente.
Varianti di formato
| Formato | Separatore | Esempio tipico |
|---|---|---|
json (predefinito) | : dopo l'eventuale virgoletta di chiusura | {"key": "value", "count": 3} |
ini | =, valore fino a fine riga | host=localhost\nport=8080 |
xml_attr | =, valore tra virgolette | <device id="42" name="sensor"/> |
xml_node | tag XML <key>…</key> | <voltage>3.3</voltage> |
Elementi annidati e ripetuti
sGetKV non valuta la profondità di annidamento. Nel caso di oggetti annidati (ad es. {"outer": {"inner": 1}}) index:0 individua la chiave esterna; una ricerca mirata di valori più in profondità richiede una valutazione in due fasi: prima estrarre il valore della chiave esterna, poi applicare di nuovo sGetKV a tale valore.
Gli elementi ripetuti con la stessa chiave (ad es. <val>10</val><val>20</val>) possono essere selezionati con index.
Esempi
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*([^;]+)'});
Suddivisione di stringhe "sSplit"
Per suddividere una stringa in corrispondenza di un carattere ch si può utilizzare la funzione sSplit. Essa restituisce una matrice a due colonne con tutte le posizioni iniziali e le lunghezze delle sottostringhe corrispondenti
r1 = sSplit(s, ch);
// Optionaler Konfigurationsblock
rx = sSplit(..., { trim: <bool>
});
pos = rx[0, 0];
len = rx[0, 1];
| Proprietà | Valore | Descrizione |
|---|---|---|
| trim | <bool> | Rimuove gli spazi bianchi all'inizio e alla fine degli elementi |
Numero di righe all'interno di una stringa "sLines"
Il numero di righe di una stringa s può essere determinato come segue
lines = sLines(s);
Sono supportate tutte le varianti di interruzione di riga (LF, CRLF, LFCR, CR).
Estrazione di una riga da una stringa su più righe "sLine"
Per estrarre l'i-esima riga da una stringa s è adatta la funzione seguente
lineI = sLine(s,i);
// Optionales Konfigurationsobjekt
lineX = sLine(..., { trim: <bool>
});
| Proprietà | Valore | Descrizione |
|---|---|---|
| trim | <bool> | Rimuove gli spazi bianchi all'inizio e alla fine della riga |
Lettura di righe complete "sGetLine"
La funzione sGetLine() collega i singoli valori del canale stringa s e li memorizza finché non può essere restituita una riga completa. Questa viene rimossa dal buffer e con il resto che rimane l'accumulo prosegue.
Per ottenere una riga completa da un flusso di caratteri si può utilizzare quanto segue
line1 = sGetLine(s);
// Optionales Konfigurationsobjekt
lineX = sGetLine(..., { trim: <bool>
, eoln: <str>
, timeout: <dbl>
});
| Proprietà | Valore | Descrizione |
|---|---|---|
| trim | <bool> | La riga restituita viene inoltre ripulita dagli spazi |
| eoln | <string> | Definizione del terminatore di riga |
| timeout | <dbl> | Tempo in secondi dopo l'ultimo frammento, trascorso il quale viene inserita una fine riga. |