Fonctions sur les chaînes de caractères
Introduction
Les chaînes de caractères (texte, string) peuvent faire partie d'un protocole d'appareil, par exemple comme message d'erreur d'un sous-système ou lors de la transmission de données de mesure via une interface série. De nombreux protocoles de communication basés sur le Web reposent eux aussi sur des chaînes.
Le module Math prend en charge le type scalaire string, qui contient en général des caractères codés en UTF-8.
Tous les types de données peuvent être convertis en type string, par exemple avec str(), ou dans les types cibles correspondants avec les autres opérateurs de cast, pour autant qu'aucune erreur de syntaxe ne se produise.
Opérateurs sur le texte
Les opérateurs suivants sont pris en charge avec le type de données string :
-
tous les opérateurs de comparaison, l'ordre numérique des caractères ASCII s'appliquant : par ex.
'4' < 'A' < 'a' -
opérateur
+, qui concatène deux chaîness_connected = s1 + s2;astucestr(x)convertit n'importe quel type de données en représentation sous forme de chaîne, y compris des objets multidimensionnels tels que des vecteurs et des matrices. Pour mieux contrôler le formatage, la fonctionsFormat(f, ...)peut être utile.
Propriétés et fonctions de base
Longueur d'une chaîne de caractères « sLength »
La longueur d'une chaîne s en octets se calcule comme suit
l = sLength(s);
Dans l'encodage UTF-8, les caractères spéciaux peuvent occuper plusieurs octets selon leur codage. Cette fonction détermine le nombre d'octets, et non le nombre de caractères (imprimables) !
Extraction d'une sous-chaîne sous forme de copie « sCopy »
Une sous-chaîne r de la chaîne s peut être extraite comme suit
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 est à de nombreux endroits le résultat de fonctions de recherche, par ex. sFind(), qui peuvent fournir plusieurs occurrences dans la chaîne. L'index sel permet d'extraire directement la partie de texte correspondante.
Exemple :
// 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;
Extraction du début et de la fin d'une chaîne « sLeft », « sRight »
Le début b et la fin e, de longueur l, de la chaîne s peuvent être obtenus sous forme de copie comme suit
b = sLeft(s,l);
e = sRight(s,l);
Suppression d'une sous-chaîne « sErase »
Pour obtenir une copie d'une chaîne s dans laquelle une sous-chaîne a été supprimée, on peut utiliser ce qui suit
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 est à de nombreux endroits le résultat de fonctions de recherche, par ex. sFind(), qui peuvent fournir plusieurs occurrences dans la chaîne. L'index sel permet de supprimer directement la partie de texte correspondante.
Insertion d'une chaîne « sInsert »
Pour insérer une chaîne t à l'intérieur d'une chaîne s à la position b et renvoyer une copie r, on peut utiliser ce qui suit
r = sInsert(s, b, t);
Création, formatage, lecture, nettoyage
Extraction de valeurs d'une chaîne « sScan » 1
Cette fonction extrait des valeurs d'une chaîne s à l'aide d'une chaîne de format f :
v = sScan(f, s);
La chaîne de format f contient des espaces réservés de la forme %<x> (la lettre après % est quelconque et n'a aucune influence sur le type du résultat) ainsi que des parties littérales qui servent de séparateurs dans la chaîne source. Pour chaque espace réservé, la partie de texte comprise entre les littéraux est extraite et convertie automatiquement dans le type de données approprié.
// 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"
| Comportement | Description |
|---|---|
| Dernier espace réservé sans littéral de fin | lit jusqu'à la fin de la chaîne |
| Guillemets autour d'une valeur | sont supprimés automatiquement |
| Littéral de la chaîne de format introuvable | renvoie cErr |
| Aucun espace réservé dans la chaîne de format | renvoie cErr |
Formatage d'une chaîne « sFormat »
Pour représenter sous forme de chaîne r formatée une chaîne f contenant par exemple des valeurs numériques, on peut utiliser la fonction suivante
r = sFormat(f, ...);
Ici, f est une chaîne de format de type printf(), et un argument correspondant de la forme %[<width>][.<precision>]<type> doit être indiqué pour chaque espace réservé.
-
<width>: largeur de champ facultative pour la sortie, width < 0 : aligné à gauche -
.<precision>: facultatif pour f/g/e, nombre de décimales ou de chiffres significatifs -
<type>: les arguments sont convertis selon le type de sortie choisi. Des indications de longueur supplémentaires pour le type de données ne sont donc pas nécessaires.<type>Type de données Sortie b <bool>Sortie de 'false' ou 'true' d <int>Entier signé, base 10 u <uint>Entier non signé, base 10 x, X <uint>Entier non signé, base 16
chiffresA-Fen minuscules (x) ou en majuscules (X)o <uint>Entier non signé, base 8 f <dbl>Nombre à virgule flottante sans exposant de 10
Exemple : 1234.5678g <dbl>Nombre à virgule flottante en représentation optimisée
comme f ou e selon l'ordre de grandeur du nombre.
Exemples : 1234.45678, 1.2345e9, 1.2345e-12e <dbl>Nombre à virgule flottante avec exposant de 10
Exemple : 1.2345678e3s <str>Texte
Exemple :
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';
Accès au contenu d'une ressource « sResource »
La fonction renvoie le contenu de la ressource indiquée sous forme de chaîne constante (binaire).
resStr = sResource({@ref:'myResource'});
Selon la configuration, le contenu de la ressource peut ne pas se limiter à du texte UTF-8 pur (par ex. un fichier INI ou un objet JSON), mais aussi comprendre des données binaires, telles que des tableaux double, des images jpg, etc. Les données binaires en particulier ne doivent être traitées que par des fonctions spécialisées appropriées. Pour l'implémentation de telles fonctions, n'hésitez pas à nous contacter.
Suppression des espaces blancs « sTrim »
Cette fonction supprime tous les espaces blancs (whitespace) au début et à la fin de l'argument, comme par exemple dans
s_trimmed = sTrim(s);
Conversion en majuscules/minuscules « sUpper », « sLower »
La conversion d'une chaîne en majuscules ou en minuscules s'effectue avec
s_uppercase = sUpper(s);
s_lowercase = sLower(s);
Simplification « sSimplify » des chaînes
La fonction sSimplify() remplace toutes les occurrences multiples d'espaces blancs (espaces, tabulations, CR, LF, ...) par un simple espace.
s_simple = sSimplify(s);
Normalisation « sNormalize » des cha înes
La fonction sNormalize() supprime les guillemets correspondants "..." ou '...' au début et à la fin de la chaîne et remplace toutes les séquences d'échappement \ par le code qu'elles désignent.
s_normalized = sNormalize(s);
Recherche, localisation et découpage
Recherche de sous-chaînes « sFind »
La fonction de recherche sFind renvoie l'index r ou une matrice contenant la position et la longueur des parties de texte trouvées correspondant au motif p dans la chaîne s ; elle s'utilise comme suit
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 aucun motif n'est trouvé, cette fonction renvoie -1.
Une matrice contenant les résultats de la recherche a la structure suivante :
Cette matrice peut être transmise directement, avec le numéro de ligne du résultat individuel, aux fonctions sCopy() ou sErase().
Un résultat individuel peut être traité plus avant avec la fonction GetRow() ou par indexation directe :
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
| Propriété | Valeur | Description |
|---|---|---|
| pattern | <str> | Motif de recherche constant, si le paramètre p n'est pas utilisé. Légèrement plus performant pour les modes regex, car l'expression n'a pas à être recompilée à chaque fois. |
| case | <bool> | Recherche avec prise en compte des majuscules / minuscules, (déf. : false, insensible à la casse) |
| all | <bool> | Renvoie un vecteur contenant les positions de début et les longueurs des parties de texte correspondantes, pas en combinaison avec subex |
| regex | <bool> | Interprète le motif pattern ou p comme expression régulière ; le résultat est une matrice contenant la position et la longueur des expressions/sous-expressions trouvées |
| subex | <bool> | Renvoie la position et la longueur des parties de texte extraites dans une matrice de résultats, active regex automatiquement |
Exemples
// 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;
Remplacement de sous-chaînes « sReplace »
Pour remplacer (plusieurs) chaînes t_k à l'intérieur de la chaîne s par les textes correspondants s_k, on peut utiliser ce qui suit
r = sReplace(s,t_1,s_1, ..., t_N,s_N);
Le remplacement s'effectue séquentiellement dans l'ordre des arguments ; les valeurs s_k sont implicitement converties en représentation textuelle. Pour mieux contrôler la conversion, la fonction sFormat() peut être utilisée.
Exemple :
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';
Recherche d'une combinaison clé-valeur « sGetKV » 1
Cette fonction recherche la clé k dans une chaîne (bloc de texte) s et renvoie la valeur associée. La recherche est insensible à la casse.
v1 = sGetKV(s, k);
// Optionaler Konfigurationsblock
vx = sGetKV(..., { format: <enum>
, filter: <regex>
, index: <uint>
});
| Propriété | Valeur | Description |
|---|---|---|
| format | <enum> | Définit le format du bloc de texte et fixe le filter par défaut approprié. Valeurs possibles : json (par défaut), ini, xml_attr, xml_node |
| filter | <regex> | Remplace la valeur par défaut du format : expression régulière qui capture, après le nom de la clé, la valeur associée comme groupe de capture (...) |
| index | <uint> | Sélectionne la N-ième occurrence (base 0, par défaut : 0). Utile lorsqu'une clé apparaît plusieurs fois, par ex. pour des éléments XML répétés. |
Si la clé n'est pas trouvée (ou si l'index dépasse le nombre d'occurrences), la fonction renvoie cErr. Les guillemets autour de la valeur trouvée sont supprimés automatiquement.
Variantes de format
| Format | Séparateur | Exemple typique |
|---|---|---|
json (par défaut) | : après un guillemet de fermeture facultatif | {"key": "value", "count": 3} |
ini | =, valeur jusqu'à la fin de la ligne | host=localhost\nport=8080 |
xml_attr | =, valeur entre guillemets | <device id="42" name="sensor"/> |
xml_node | balise XML <key>…</key> | <voltage>3.3</voltage> |
Éléments imbriqués et répétés
sGetKV n'évalue pas la profondeur d'imbrication. Pour les objets imbriqués (par ex. {"outer": {"inner": 1}}), index:0 correspond à la clé extérieure ; une recherche ciblée de valeurs situées plus profondément nécessite une évaluation en deux étapes : extraire d'abord la valeur de la clé extérieure, puis appliquer de nouveau sGetKV à celle-ci.
Les éléments répétés portant la même clé (par ex. <val>10</val><val>20</val>) peuvent être sélectionnés avec index.
Exemples
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*([^;]+)'});
Découpage de chaînes « sSplit »
Pour découper une chaîne en un caractère ch, on peut utiliser la fonction sSplit. Elle renvoie une matrice à deux colonnes de toutes les positions de début et longueurs des sous-chaînes correspondantes
r1 = sSplit(s, ch);
// Optionaler Konfigurationsblock
rx = sSplit(..., { trim: <bool>
});
pos = rx[0, 0];
len = rx[0, 1];
| Propriété | Valeur | Description |
|---|---|---|
| trim | <bool> | Supprime les espaces blancs au début et à la fin des éléments |
Nombre de lignes d'une chaîne « sLines »
Le nombre de lignes d'une chaîne s peut être déterminé comme suit
lines = sLines(s);
Toutes les variantes de sauts de ligne sont prises en charge (LF, CRLF, LFCR, CR).
Extraction d'une ligne d'une chaîne multiligne « sLine »
Pour extraire la i-ème ligne d'une chaîne s, la fonction suivante convient
lineI = sLine(s,i);
// Optionales Konfigurationsobjekt
lineX = sLine(..., { trim: <bool>
});
| Propriété | Valeur | Description |
|---|---|---|
| trim | <bool> | Supprime les espaces blancs au début et à la fin de la ligne |
Lecture de lignes complètes « sGetLine »
La fonction sGetLine() assemble les différentes valeurs du canal de chaînes s et les mémorise jusqu'à ce qu'une ligne complète puisse être émise. Celle-ci est retirée du tampon et l'accumulation se poursuit avec le reste.
Pour obtenir une ligne complète à partir d'un flux de caractères, on peut utiliser ce qui suit
line1 = sGetLine(s);
// Optionales Konfigurationsobjekt
lineX = sGetLine(..., { trim: <bool>
, eoln: <str>
, timeout: <dbl>
});
| Propriété | Valeur | Description |
|---|---|---|
| trim | <bool> | La ligne émise est en outre débarrassée de ses espaces |
| eoln | <string> | Définition de la fin de ligne |
| timeout | <dbl> | Temps en secondes après le dernier fragment avant qu'une fin de ligne soit insérée. |