• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

String zurechtschneiden in einem Command

Hallo,

wenn ich einen String wie z. B. ein Datum zurechtschneiden will, muss ich bisher mit meinen bescheidenen Kenntnissen in 2 Schritten vorgehen, z. B. wenn ich den Monat haben will (ich weiß, dass das bei Datum mit 'date' geht, mir ist nur kein anderes Bsp. eingefallen). Zunächst schneide ich wie hier http://www.christian-hoenick.com/blog/2012/01/06/shell-string-abschneiden-oder-entfernen-teilstring/ beschrieben alles bis zum ersten Auftreten des Punktes von vorne, dann alles bis zum ersten Auftreten des Punktes von hinten weg.

Code:
a=${VALUE#*.}
b=${a%.*}
echo $b

Geht das auch in einem Command? Vermutlich mit sed oder awk, damit hab ich aber überhaupt keine Erfahrung und ich denke das ist hier auch Overkill.
 

framp

Moderator
Teammitglied
Es geht auch mit bash Mitteln wenn Du das Tool cut benutzt:
Code:
b=$(cut -f 2 -d '.')
 
A

Anonymous

Gast
bunter fisch schrieb:
Hallo,

wenn ich einen String wie z. B. ein Datum zurechtschneiden will, muss ich bisher mit meinen bescheidenen Kenntnissen in 2 Schritten vorgehen,....
Zunächst schneide ich wie hier http://www.christian-hoenick.com/blog/2012/01/06/shell-string-abschneiden-oder-entfernen-teilstring/ beschrieben alles bis zum ersten Auftreten des Punktes von vorne, dann alles bis zum ersten Auftreten des Punktes von hinten weg.

Code:
a=${VALUE#*.}
b=${a%.*}
echo $b

Was hier umständlich aussieht ist gegebenenfalls genau die optimale Lösung bei einer Shell. und zwar dann, wenn dieses innerhalb des Scriptes nicht hundertfach gemacht werden muss, und der String der zurechtgeschnitten werden muss, schon in einer Variable steht.

Warum genau das Richtige?
  • # 2 einzelne Befehle die ihrerseits beide einzeln gut getestet werden können,

    # der Sinn und die Funktion der beiden Befehle ist auch später wieder recht gut und schnell aus dem Script herauszulesen.

    # beide Befehle laufen in der Shell faktisch ohne Resourcen- und Zeitverschwendung

    # eine direkte Verknüpfung dieser und ähnlicher Parameter-Expansions Funktionen in der Shell zu genau einem einzigem Aufruf, sind meist nicht machbar, und wenn in wenigen Einzelfällen doch, dann sehr schwer zu debuggen, zu analysieren und zu interpretieren, wenn da was schiefläuft, oder es mal nicht wirklich richtig passt.

    # Besser hier wirklich einzelne aufeinander folgende Befehle mit klar definierten Einzelaufgaben die in der Summe die Gesamtaufgabe erfüllen. Das ist bei weitem kein schlechter Programmierstiel.


sed, awk, cut, .......?
  • # es handelt sich nicht um Shellinteren Aufrufe sondern dieses sind System-Aufrufe.

    # alle diese Tools können nicht direkt aus einer Shell Variable lesen, es muss also zB. ein echo mit einer Pipe davor gesetzt werden.

    # Das Ergebnis kann typischer Weise nur entweder direkt rausgeschrieben oder mittels Kommandosubstition in eine Variable geschrieben werden.

    # Sowohl der Systemaufruf, als auch die Pipe und Kommandosubstitution sind intern in der Shell aufwendig und relativ langsam.

Den Geschwindigkeitsunterschied könnte man gut ermitteln, wenn man beide Verfahren in einer Schleife 10000 mal ausführen würde, (ohne echo) und die Laufzeit mittels time ermitteln und vergleichen würde.
Code:
robi@linux~#   VALUE="10.05.2019"
robi@linux~#   time  for i in $(seq 1 10000)
do
   a=${VALUE#*.}
   b=${a%.*}
   # echo $b
done

real    0m0.057s
user    0m0.050s
sys     0m0.003s

robi@linux~#   time    for i in $(seq 1 10000)
do
   b=$(echo $VALUE | cut -d '.' -f 2)
   # echo $b
done

real    0m26.701s
user    0m5.760s
sys     0m13.507s

Wie geeignet sind die anderen Tools?
cut :
  • # ist verwendbar wenn man einen festen "Delimeter" und damit feste Felder bestimmen kann.

    # ist auch gut verwendbar wenn man mit genauen Byteposition oder genauen definierten Stringlängen arbeiten kann.

    # Vorsicht hier mit Sonderzeichen, (nicht druckbare Zeichen machen hin und wieder Probleme und müssten vorher entfernt werden.)

sed :
  • # entweder man macht es technis genauso wie in der Shell, Anfang wegschneiden, Ende Wegschneiden, ausgeben.

    # oder den gewünschten Teilstring genau beschreiben und nur dieses ausgeben.

    # sowohl bei der ersten, als auch bei der zweiten Variante ist die Beschreibungssyntax Regex, damit sollte man schon etwas umgehen können.

awk :
  • # etwas besser geeignet wie cut wenn verschiedene Delimeter benutzt werden, zB Tab+Space ; oder (); {}, .........

    # kann auch analog sed genutzt werden

    # ist aber eigentlich eine komplette Programmiersprache sogar mit schon enthaltenen Stringfunktionen, und, und, und

    # für diese einfache Aufgabe oftmals viel zu mächtig.


Ganz anders sieht es aus wenn ?

  • # wenn der String noch irgendwo in einer Datei steht, und dort zB genau 1 Mal pro Zeile und das ganze 1000 Zeilen lang, und von jeder Zeile soll dort immer ein Substring ermittelt werden.

    # Oder wenn dieser Substring tausendfach ermittelt werden soll und zwar unmittelbar vor der Ausgabe, eventuell auch noch genau ein mal pro Zeile.

    # Oder wenn der String irgendwo innerhalb einer Eingabedatei mehrfach vorkommt, aber es neben dem dem Zeilenformat in dem der String steht, es auch noch andere Zeilenformat gibt, in denen etwas Sinngemäß ganz anderes drin steht, die Zeilen also eventuell ganz anders zu interpretieren und Daten daraus unterschiedlich zu extrahieren sind.

Prinzipiell wenn dieses hundert oder tausendfach bei Eingabe oder Ausgabe gemacht werden soll, dann eignet sich ein Filterbefehl zB mit cut, sed, oder awk oftmal sehr gut. Man sollte aber darauf achten, dass wenn möglich dieser Befehl nur einmal aufgerufen wird, und dann alle Zeilen auf einen Schlag bearbeitet, und nicht etwa pro Zeile der Befehl dann jedes mal neu aufgerufen wird.
Je komplizierter die Ein- und Ausgabedaten werden, desto problematischer würde die String Bearbeitung rein mit Shell-Mitteln werden, es sind nunmal nur ein paar dieser Parameter-Expansionen und -Substitutions Funktionen welche die Shell kennt und die sind nicht selten so starr, dass sie in etwas komplizierten Fällen einfach nicht ausreichen und man auf externe Kommandos für Textverarbeitung mit Regex-Unterstützung setzen muss.

robi
 
Oben