Filtern in Bash

Manchmal will man aus einer Variable oder einem Text alle Zahlen herausziehen oder verstecken. Das geht natürlich mit sed ganz gut, aber noch einfacher in der Bash selbst.

% VAR=1a2b3c4d
% echo "${VAR//[!0-9]/}"
1234
% echo "${VAR//[0-9]/}"
abcd

Man kann auch nur Buchstaben filtern, damit man Sonderzeichen mit herausfiltert. Oder oder…

% VAR="1a,2b.3c;4d"
% echo "${VAR//[!0-9]/}"
1234
% echo "${VAR//[!a-z]/}"
abcd
% echo "${VAR//[!a-z 0-9]/}"
1a2b3c4d
% echo "${VAR//[a-z 0-9]/}"
,.;
Advertisements
Filtern in Bash

Spielen mit Variablen

Variablen machen ein Script schon fast zu einem Programm. Daher sollte man sich ein wenig mit den Möglichkeiten auseinandersetzen. Man spart sich dann Aufrufe von Hilfsprogrammen wie awk, sed oder cut.

  1. Default-Wert: Wenn man eine Variable etwa in einer Operation verwendet und die Operation einen Wert erwartet, die Variable aber u.U. leer sein kann, dann muss man einen Default-Wert definieren. Ich mache das üblicherweise so, dass ich die Variable vorher mit dem Default-Wert setze, damit sie in jedem Fall existiert. Aber: Das muss man nicht! Man kann die Variable auch so ausgeben:
    $ echo $N
    
    $ echo ${N-0}
    0
    $ N=1
    $ echo ${N-0}
    1

    Hier wird der Default-Wert ausgegeben, ohne die Variable selbst zu ändern. Will man in dem Fall, dass die Variable ungesetzt ist, sie mit einem Wert setzen, geht das mit :=

    $ echo $N
    
    $ echo ${N:=0}
    0
    $ echo $N
    0
    
  2. Manchmal benötigt man nur einen Teil einer Variable, etwa die ersten drei Zeichen. Man kann dann mit ‚cut‚ arbeiten oder andere komplizierte Lösungen finden, oder man nutzt einfach einen entsprechenden Aufruf der Variable:
    $ N=123456789
    $ echo $N
    123456789
    $ echo ${N:0:3}
    123
    $ echo ${N:2:3}
    345
    $ echo ${N:2:-3}
    3456

    Der erste Fall gibt drei Zeichen der Variable, beginnend mit Position 0 (Anfang) und der zweite Fall beginnend mit Position 2 (drittes Zeichen). Der dritte zeigt alle Variablen ab Stelle 2 und bis zieht die letzten drei ab.

  3. Die Länge einer Variable ist auch oft interessant:
    $ N=123456789
    $ echo ${#N}
    9
    

    Und damit kann man auch den Anfang einer Variable nach Beispiel in 2. beschneiden (auch wenn #N hier sogar zu groß ist, aber es ist niemals zu klein):

    $ N=123456789
    $ echo ${N:2:${#N}}
    3456789
  4. Suchen und Ersetzen/Löschen geht auch:
    $ N=123456789
    $ echo ${N//2/3}
    133456789
    $ echo ${N//2/}
    13456789
    

Falls ich über weitere spannende Variablenspielerreien stolpere, werde ich darüber berichten!

Spielen mit Variablen

<html>-Tags löschen

Um aus einer Datei alle html-Tags zu löschen, bietet sich sed an. Ich dachte erst, das geht einfach so:

's/<.*>//g'

Aber damit löscht mann alles zwischen dem ersten < und dem letzten >. So geht es:

sed -e 's/<[^>]*>//g'

Warum? Dinge in eckigen Klammern sind Zeichenklassen, etwa steht [0-9] für alle Zahlen. Steht ein ^ davor, dann dreht es das um, also alles, was nicht in der Klammer steht. Beispiele:

$ echo t12e34x5678t | sed 's/[0-9]//g'
text
$ echo t12e34x5678t | sed 's/[^0-9]//g'
12345678

Im obigen Befehl werden alle Zeichen vom < und null oder beliebig viele, die nicht > sind bis zum > ersetzt.

<html>-Tags löschen

Zeilenumbrüche löschen

Mit sed leider nicht so einfach, wie man denken würde. So geht es:

sed ':a;N;$!ba;s/\n/ /g'

Jeder Zeilenumbruch wird durch ein Leerzeichen ersetzt.

Ich brauchte das, um Zeilenumbrüche zu löschen, bei denen die nächste Zeile mit einem bestimmten Zeichen beginnt. Man kann also hinter das \n noch mehr Zeichen für das Suchpattern schreiben. Beispiel:

sed ':a;N;$!ba;s/\nA/ A/g'

Lösche alle Zeilenumbrüche, bei denen die nächste Zeile mit A beginnt.

Zeilenumbrüche löschen

sed räumt auf

Mit sed (nein, nicht die Partei, sondern der stream editor) kann man Suchen und Ersetzen auf komplexeste Weise. Ich will immer mal wieder Configdateien bereiningen. Dieser Befehl löscht alle auskommentierten Zeilen und alle Leerzeilen und löscht alle Leerzeichen am Ende einer Zeile:

sed -e 's/#.*//' -e 's/[ ^I]*$//' -e '/^$/ d' 

Mit ^I ist Tab gemeint, den man auch so eintippen muss.

Auch nervig ist das ^M am Ende von Dateien die mit Windows bearbeitet wurden. So wird man es los:

sed -e 's/^M//'

Das ^M muss man als Ctrl-V, Ctrl-M eingeben!

sed räumt auf