De:Chapter 10
Contents
Grundlagen über Strings und Zeichenketten
Dieser Abschnitt behandelt die Verarbeitung von Zeichenketten (Trennung, Vergleich, Umformung, Umkehrung, Speicherung). Viel Spass.
Als erstes wird die Trennung von Zeichenketten behandelt. Die häufigste und einfachste Art nutzt Kommata (,). Die meisten Funktionen in Sphere nutzen sie als Trennzeichen und es ist einfacher als Leerzeichen zu benutzen. Auch Leerzeichen sind gültige Trennzeichen, aber werden kaum verwendet. Diese Funktion stellt dar, warum das so ist:
[FUNCTION f_test] SERV.LOG Arguments :: <ARGV> SERV.LOG Arg. 1 :: <ARGV[0]> SERV.LOG Arg. 2 :: <ARGV[1]> SERV.LOG Arg. 3 :: <ARGV[2]> SERV.LOG Arg. 4 :: <ARGV[3]>
Wenn wir nun IG ".f_test Hello to all World" eingeben, dann sehen wir sowas in der Sphere Konsole:
23:01:(Test.scp,2)Arguments :: 1 23:01:(Test.scp,3)Arg. 1 :: Hello To all World 23:01:(Test.scp,4)Arg. 2 :: 23:01:(Test.scp,5)Arg. 3 :: 23:01:(Test.scp,6)Arg. 4 ::
Das bedeutet, dass nur ein Argument der Funktion erkannt wurde und es die komplette Zeichenkette war. Das ist nicht nützlich, denn später muss diese Zeichenkette mit STRARG oder STREAT zerschnitten werden. Aber wenn nun die Leerzeichen mit Kommata ersetzt werden, indem ".f_test Hello,to,all,World" eingebenen wird:
23:02:(Test.scp,2)Arguments :: 4 23:02:(Test.scp,3)Arg. 1 :: Hello 23:02:(Test.scp,4)Arg. 2 :: To 23:02:(Test.scp,5)Arg. 3 :: All 23:02:(Test.scp,6)Arg. 4 :: World
Somit wurde der komplette String zertrennt. Einfach? Ja, aber das ist auch nur der Anfang.
Man kann fast alles mit Zeichenketten anstellen, was man will: Vergleichen, Zerschneiden, Löschen, Verschieben, usw ... Um alle gültigen Operationen zu sehen, gibt es eine Auflistung unten.
Operationen auf Zeichenketten
EXPLODE
Die EXPLODE Opteration wandelt automatisch beliebige Trennzeichen in Kommata um. Das Ergebnis kann an eine Funktion übergeben werden, die dann mittels ARGV auf die Einzelteile zugreifen kann.
Syntax von EXPLODE: EXPLODE Trennzeichen, Zeichenkette
Das folgende Beispiel verwandelt "-"- und "+"-Zeichen in Kommata und schreibt die Ausgabe in das Log der Sphere Konsole:
[FUNCTION f_explode] F_EXPLODE_LOG <EXPLODE -+,<ARGS>> // Trennt den String bei - und + und übergibt das Ergebnis an F_EXPLODE_LOG [FUNCTION f_explode_log] SERV.LOG ARGV Length = <ARGV> // Gibt die Anzahl der Einzelteile aus FOR 0 <EVAL (<ARGV> - 1)> // Schleife über alle Einzelteile SERV.LOG ARGV[<LOCAL._FOR>] = <ARGV[<LOCAL._FOR>]> // Ausgabe eines Einzelteils ENDFOR
STRARG
STRARG liefert das erste Wort in einer Zeichenkette. Demonstrationsbeispiel:
[FUNCTION f_strarg] SERV.LOG <STRARG Eins Zwei Drei>
In der Konsole erscheint das Wort "Eins".
STREAT
STREAT macht genau das Gegenteil von STRARG. Während STRARG das erste Wort in einem String liefert, löscht STREAT das erste Wort und liefert den Rest. Demonstrationbeispiel:
[FUNCTION f_streat] SERV.LOG <STREAT Eins Zwei Drei>
In der Konsole erscheint der Text "Zwei Drei".
STRCMP
Früher oder später müssen Zeichenketten miteinander verglichen werden. Als erstes sollte man folgendes versuchen:
IF ("String1" == "String2")
Falls du das versuchst, wird ein ziemlich hässlicher Fehler auf der Sphere Konsole auftauchen und das IF-Statement wird nicht richtig arbeiten. Der Grund dafür ist, dass IF-Statements dafür ausgelegt sind Zahlen zu vergleichen. Deshalb kann es den Vergleich zwischen zwei Zeichenketten nicht auswerten.
Es wird also eine Möglichkeit benötigt "string1" und "string2" auf Gleichheit zu prüfen, richtig? Deshalb gibt es STRCMP.
STRCMP(string1, string2)
Bevor STRCMP benutzt wird, sollte allerdings darauf eingangen werden, dass diese Funktion nicht wirklich zwei Zeichenketten auf Gleichheit überprüft. In Wahrheit liefert STRCMP einen lexikalischen Vergleich und gibt zurück, ob eine Zeichenkette größer oder kleiner als die andere ist (nach alphabetischer Ordnung). Deshalb liefert diese Funktion drei Ergebniswerte:
Rückgabewert | Bedeutung |
-1 | string1 ist kleiner als string2 |
0 | beide sind gleich |
1 | string1 ist größer als string2 |
Man sollte die Semantik dieser Funktion im Kopf haben, denn die Funktion liefert naturgemäß "false" (= 0) innerhalb eines IF-Statements, wenn beide Zeichenketten gleich sind.
Hier ein Beispiel:
IF !(STRCMP(<SRC.NAME>, Klein)) SRC.SAY Mein Name ist Klein! ENDIF
Nun könnte man noch fragen: "Warum muss STRCMP nicht von < > eingeschlossen werden?".
Der Grund ist, dass STRCMP keine 'normale' Funktion ist. Es ist eine intrinsic function, eine spezielle Funktion, die nur innerhalb von <EVAL ...>-Statements benutzt werden kann und anstelle von < > die Argumente mit ( und ) einschließt.
"Moment, aber STRCMP wird nicht innerhalb eines EVAL benutzt?!", könnte man jetzt sagen. Aber die Eigenheit von konditionalen Statements (wie IF und WHILE) ist, dass Sphere automatisch die angebene Bedingung so behandelt, als wäre ein EVAL-Statement vorhanden. Deshalb funktioniert obiges Skript und vergleicht zwei Zeichenketten.
Des Weiteren ist wichtig zu wissen, dass STRCMP auch Groß- und Kleinschreibung prüft. Deshalb ist "STRING1" nicht gleich "string1". Ein Vergleich, der Groß- und Kleinschreibung ignoriert, kann mit STRCMPI durchgeführt werden.
STRCMPI
STRCMPI vergleicht zwei Zeichenketten und ignoriert dabei Groß- und Kleinschreibung. Bis auf diesen Unterschied ist die Funktionsweise mit STRCMP identisch.
STRLEN
Diese Funktion liefert die Anzahl von Zeichen in einer Zeichenketten. Beispielsweise:
LOCAL.LENGTH = <EVAL STRLEN(<ARGS>)>
Angenommen der Inhalt von ARGS wäre "Hier stehen 22 Zeichen". Dann ist LOCAL.LENGTH = 22.
STRPOS
STRPOS liefert die Position eines spezifischen Zeichens innerhalb einer Zeichenkette. Die Syntax dieser Funktion ist:
STRPOS pos ch string
Parameter | Bedeutung |
pos | Die Startposition ab der nach ch gesucht werden soll. Das erste Zeichen steht auf Position 0. |
ch | Das zu suchende Zeichen oder der ASCII-Code des zu suchenden Zeichens. |
string | Der Text, der durchsucht werden soll. |
Hier ein paar Beispiele:
LOCAL.POS = <STRPOS 0 32 Wo ist das erste Leerzeichen> // Rückgabewert: 5 LOCAL.POS = <STRPOS 3 e Wo ist das erste 'e''> // Rückgabewert 11
STRREVERSE
Diese Funktion kehrt einfach die die Zeichenkette um. Beispielsweise:
SERV.LOG <STRREVERSE Hallo>
Diese Zeile gibt auf der Konsole "alloH" aus.
STRSUB
STRSUB kann aus einer Zeichenkette eine Folge von Zeichen extrahieren. Warum das nützlich ist? Es gibt einige Gelegenheiten und sicherlich will man darauf vorbereitet sein:
[FUNCTION TestStrSub] SERV.LOG <STRSUB 0 1 Hallo>
Wie ersichtlich werden für STRSUB drei Parameter benötigt. Der erste ist die Startposition (beginnend bei 0). Der zweite Parameter ist die Länge und schlussendlich ist der dritte Parameter die Zeichenkette.
Wird diese Funktion IG aufgerufen, dann erscheint in der Konsole das erste Zeichen ab der dritten Position. Wichtig ist, dass die erste Position bei 0 beginnt. Wird ein Teilstring ab der allerersten Position benötigt, dann sollte man 0 als ersten Parameter setzen. Der zweite Parameter gibt an, wieviele Zeichen ab der angegebenen Position zurückgegeben werden sollen.
Ein negativer Wert als erstes Parameter weist Sphere an, am Ende der Zeichenkette zu beginnen und von dort aus rückwärts zu zählen. Hier ist ein Beispiel:
[FUNCTION TestStrSub] SERV.LOG <STRSUB -1 1 Hallo>
Bei Benutzung dieser Funktion IG wird das letzte Zeichen auf der Konsole ausgegeben.
Das ist nicht zu schwierig, oder?
STRTOLOWER
Diese Funktion verwandelt alle Großbuchstaben einer Zeichenkette in Kleinbuchstaben. Ein einfaches Beispiel:
LOCAL.LOWER = <STRTOLOWER MIt ZeicHENkEtTen herUmSpIelEN ist LusTIG>
Diese Funktion liefert "mit zeichenketten herumspielen ist lustig".
STRTOUPPER
Diese Funktion macht das genaue Gegenteil von STRTOLOWER. Sie wandelt alle Kleinbuchstaben in Großbuchstaben. Das vorherige Beispiel mit STRTOUPPER:
LOCAL.UPPER = <STRTOUPPER MIt ZeicHENkEtTen herUmSpIelEN ist LusTIG>
Diese Funktion liefert "MIT ZEICHENKETTEN HERUMSPIELEN IST LUSTIG".
STRTRIM
Diese Funktion entfernt alle Leerzeichen (echte Leerzeichen, Tabulatoren und Zeilenumbrüche) am Anfang und am Ende einer Zeichenkette.
Das folgende Skript demonstriert dies:
[FUNCTION f_strtrim] LOCAL.TEXT = " TEST " SERV.LOG 1. <LOCAL.TEXT> SERV.LOG 2. <STRTRIM <LOCAL.TEXT>>
Als Ergebnis wird auf der Konsole ausgegeben:
1. TEST
2. TEST
STRMATCH
Die STRMATCH Funktion ermöglicht die Benutzung von sogenannten Wildcards (*).
Die Syntax dieser Funktion ist STRMATCH(pattern, string). Sie liefert 1, wenn der String zu pattern passt und 0 wenn nicht. Ein Beispiel hierfür:
[FUNCTION f_strmatch] IF (STRMATCH(*ex*, <ARGS>)) SERV.LOG ARGS enthält 'ex'! ELSE SERV.LOG ARGS passt nicht. ENDIF
In der Konsole kann nun F_STRMATCH Mexico aufgerufen werden. Als Ergebnis wird "ARGS enthält 'ex'!" ausgegeben. Mit einigen verschiedenen Experimenten kann leicht die Funktionsweise erschlossen werden.
War interessant? STRMATCH ist in Wahrheit noch um einiges mächtiger als das. * ist nur ein spezielles Zeichen, das innerhalb von pattern benutzt werden kann:
Pattern | Bedeutung |
* | Stimmt mit einer beliebigen Anzahl von Zeichen überein - inklusive keinem. |
? | Stimmt mit exakt einem beliebigen Zeichen überein. |
[\*] | Stimmt exakt mit '*' überein. |
[abcdef] | Stimmt mit irgendeinem der Zeichen der Liste überein. |
[!abc] [^abc] |
Stimmt mit irgendeinem Zeichen überein, der sich nicht in der Liste befindet. |
[a-z] | Stimmt mit jedem Zeichen zwischen a und z überein. |
Das ist alles, was man über STRMATCH wissen muss. Eine letzte Anmerkung noch: pattern ignoriert Groß- und Kleinschreibung immer (beispielsweise wird das *ex*-Beispiel auf "TEXT" auch liefern, dass ex enthalten ist).
Anmerkung: Manche Nutzer benutzen STRMATCH auch dafür, um die Gleichheit zweier Zeichenketten zu bestimmen. Das ist nicht der Bestimmungszweck dieser Funktion und hat einige Nachteile:
- Sphere wird versuchen, eine Übereinstimmung nach pattern zu berechnen und dabei weniger performant sein.
- Wenn eines der speziellen Zeichen (bspw '*') in der ersten Zeichenkette enthalten ist, dann kann es unter umständen dazu führen, dass das Ergebnis nicht das ist, was erwartet wird (beispielsweise etwas ähnliches zu STRMATCH(<ARGS>, IRGENDEINTEXT)), und ARGS enthält zufällig *INT*).
Sollen zwei Zeichenketten auf Gleichheit geprüft werden, sollten die STRCMP or STRCMPI Funktionen verwendet werden.
STRREGEX
STRREGEX bietet weitaus mächtigere Patterns als STRMATCH.
Angenommen eine Zeichenkette soll darauf geprüft werden, ob sie eine Gleitpunktzahl ist (eine Zahl mit einem Komma). Mit STRMATCH könnte folgendes versucht werden:
[FUNCTION f_fpmatch] IF (STRMATCH([0-9].[0-9], <ARGS>)) SERV.LOG <ARGS> ist eine Gleitpunktzahl. ELSE SERV.LOG <ARGS> ist keine Gleitpunktzahl. ENDIF
Wird der Befehl F_FPMATCH 1.0 in der Konsole abgesetzt, dann wird das pattern erfolgreich erkannt, aber wird eine größere Zahl als 9.9 übergeben oder eine Zahl die mehr als nur eine Nachkommastelle hat, dann wird diese nicht erkannt. Man könnte nun mehrere "[0-9]" angeben, allerdings würde das keine Lösung für das Problem bedeuten, denn es wird immer genau auf eine feste Anzahl geprüft. Beispielsweise könnte STRMATCH([0-9][0-9][0-9].[0-9][0-9][0-9], <ARGS>) benutzt werden. Dann würde 001.500 passen, aber 1.5 nicht.
STRREGEX bietet hierfür eine Lösung indem reguläre Ausdrücke benutzt werden um eine weitaus mächtigere Art der Mustererkennung zu unterstützen. In der Tat sind reguläre Ausdrücke so mächtig, dass sie für sich genommen eine eigene Sprache sind und deshalb kann innerhalb dieser Hilfe nur eine kleine Einführung geboten werden, wie reguläre Ausdrücke arbeiten. Um mehr darüber zu lernen, bietet sich eine Recherche im Web an, beispielsweise regular-expressions.info (auf Englisch) oder Tutorial für reguläre Ausdrücke (auf Deutsch).
Um nun eine Gleitpunktzahl mit regulären Ausdrücken zu erkennen, kann folgendes Pattern verwendet werden:
^[-+]?[0-9]*\.?[0-9]+$
Falls die Sprache für reguläre Ausdrücke für dich zu schwierig erscheint, dann sieht das sicherlich wie eine zufällige Ansammlung von Symbolen und Zeichen aus. Aber eigentlich ist das ein einfaches Beispiel für einen regulären Ausdrück. Glücklicherweise ist der Ausdruck sicherlich korrekt (laut Autor) und es kann in STRREGEX benutzt werden. Die obige funktion kann folgendermaßen modifiziert werden:
[FUNCTION f_fpmatch] IF (STRREGEX(^[-+]?[0-9]*\.?[0-9]+$, <ARGS>)) SERV.LOG <ARGS> ist eine Gleitpunktzahl. ELSE SERV.LOG <ARGS> ist KEINE Gleitpunkzahl. ENDIF
So kompliziert es aussieht, es funktioniert sehr gut. Beispielsweise mit folgenden Werten: "1.5", "-250.002", "50", and even ".007".