sed

Bash: Variablen Bearbeiten

Written by  on September 24, 2015

Die Bash kann einiges mit Variablen anstellen, was man in vielen Scripten relativ kompliziert gelöst sieht.

Ein Beispiel, das in vielen Scripten vorkommt: Eine Ausgabedatei soll genau so heißen wie die Eingabedatei, aber eine andere Erweiterung haben.

A="test.txt"
B="${A%%.txt}.csv"

Was steht jetzt in Variable B?

echo $B
test.csv

Wie funktioniert das?
Mit dem ‘%’-Operator kann man von einer Variable Zeichen vom Ende her löschen.
Mit ‘%%’ werden auch mehrere Vorkommen der Variable vom Ende her gelöscht.

Vom Anfang her löschen geht mit ‘#’

Ersetzen ähnlich wie mit sed geht über den ‘/’-Operator, ‘^’ und ‘,’ machen Groß- bzw. Kleinbuchstaben.

Schöne Beispiele dazu finden sich im Web z.B. beim Linuxmagazin.

Näheres dazu ist unter dem Suchbegriff “Parameter Expansion” zu finden. Auch in der Manpage von bash.

Die Bash austricksen

Written by  on Januar 30, 2015

Folgende Problemstellung: In einem Shellscript soll eine Variable unter einfachen Hochkomma eingefügt werden. Von Haus aus geht das nicht, weil das einfache Hochkomma die Variable vor dem Auflösen durch die Shell schützt. Durch doppelte Hochkomma ersetzen geht auch nicht, weil die ebenfalls schon vorkommen und erhalten bleiben sollen weil diese Syntax noch vom nächsten Tool an diesen Stellen nötig sind.

> X=xy
> echo '"ab" "cd" "$X"'
"ab" "cd" "$X"

So klappt es schon mal nicht. Statt $X hätten wir gerne “xy” da stehen. Was liegt also näher, als mit dem gut alten sed zu ersetzen?

echo $(echo '"ab" "cd" "$X"' | sed s/\$X/$X/g)
"ab" "cd" "xy"

Schon klappt die Ersetzung.
Wie funktioniert das jetzt genau? Im sed wird der String “$X” mit dem Inhalt von $X ersetzt. Wichtig ist dabei das $-Zeichen mit einem \ zu quoten.

Speed Up Search & Replace in Shellscripts

Written by  on Oktober 3, 2014

Als erstes erzeugen wir ein paar Testdaten:

for i in {0..100000..1}; do echo "y $i $RANDOM "; done > testfile

Die Testdaten sehen jetzt etwa so aus (ca. 15MB):

head testfile
y 0 8229
y 1 32515
y 2 13193
y 3 31231
y 4 27663
y 5 24114
y 6 20325
y 7 5351
y 8 1576
y 9 21936
Wir ersetzen alle y durch x mit awk:
# time awk '{ print "x "$2" "$3 }' < testfile > /dev/null
real 0m5.942s
user 0m5.672s
sys 0m0.088s

und jetzt mit sed

# time sed s/"y"/"x"/g testfile > /dev/null
real 0m4.870s
user 0m4.644s
sys 0m0.072s

Wir schränken die suche ein – nach dem ersten Treffer darf abgebrochen werden

# time sed s/"y"/"x"/ testfile > /dev/null
real 0m3.560s
user 0m3.380s
sys 0m0.084s

Wir suchen gezielt nach Zeilenanfang

# time sed s/"^y"/"x"/ testfile > /dev/null
real 0m3.604s
user 0m3.416s
sys 0m0.104s

Und ersetzen auch Zeilenanfang

# time sed s/"^y"/"^x"/ testfile > /dev/null
real 0m3.575s
user 0m3.428s
sys 0m0.064s

Fazit: Wenn man das richtige Werkzeug zur richtigen Zeit benutzt lassen sich recht einfach 40% einsparen! AWK schneidet hier deutlich langsamer ab, weil erst die Parameter geparsed werden müssen!