shellscripts:shellscripts

Shellscripts

Eine Sammlung eigener und fremder Shellskripte.

Grundsätzlich macht man ein Shellsripte ausführbar (chmod +x DATEI).

Für den Debugmodus ändert man einfach die erste Zeile, der sog. Shebang, in

  #!/bin/sh -x
  • dauerhaft
    • Systemweit:
      echo "set bell-style none" >> /etc/inputrc
    • für den aktuellen Benutzer:
      echo "set bell-style none" >> ~/.inputrc
  • sofort
    • Console:
      • Disable: setterm -blength 0
      • Enable: setterm -blength 200
    • X11:
      • Disable: xset b off
      • Enable: xset b on
Umleitungsschema Wirkung
Befehl > ausgabe.log

(auch:

Befehl 1> ausgabe.log
Die (Standard-)Ausgabe (STDOUT) wird in die Datei ausgabe.log geschrieben (diese Datei wird, falls vorhanden, komplett durch die Ausgabe von cmd überschrieben.
Befehl > ausgabe.log
Die (Standard-)Ausgabe (STDOUT) wird an die Datei ausgabe.log angehängt
Befehl 2> ausgabe.log
Die (Standard-)Fehlerausgabe (STDERR) wird in die Datei ausgabe.log geschrieben
Befehl 2>> ausgabe.log
Die (Standard-)Fehlerausgabe (STDERR) wird an die Datei ausgabe.log angehangen
BefehlA | BefehlB 
Ausgabe des BefehlA an BefehlB übergeben (pipen)
Befehl < eingabe.txt
Die (Standard-)Eingabe wird aus der Datei eingabe.log genommen (nicht von der Tastatur).
Befehl << EOT eingabe.log
Die (Standard-)Eingabe wird aus der Datei eingabe.log genommen (nicht von der Tastatur). Aber nur bis zur (frei wählbaren!) Zeichenfolge EOT. Es handelt sich um ein HERE-Dokument.
Numeric handles:
Name Bedeutung
STDIN = 0 Keyboard input
STDOUT = 1 Text output
STDERR = 2 Error text output
UNDEFINED = 3-9
Umleitung nach /dev/null (Fehlermeldungen verbergen):
Befehl 2> /dev/null 
Fehlermeldungen an /dev/null umleiten
Befehl >/dev/null 2>&1 
Fehlermeldungen und Ausgaben an /dev/null umleiten
Befehl >Dateiname 2> /dev/null 
Fehlermeldungen an /dev/null, die Ausgaben jedoch an „Dateiname“ umleiten
  • STDERR und STDOUT an ausgabe.log anhängen:
    die echo ausgabe.log >> test.txt 2>&1
  • die Eingabe aus eingabe.txt holen, STDOUT auf ausgabe.log und STDERR auf fehler.log leiten
    cmd < eingabe.txt > ausgabe.log 2> fehler.log
  • die Eingabe aus eingabe.log holen und STDERR auf STDOUT (2>&1) umlenken:
    cmd < eingabe.txt > ausgabe.log 2>&1

    wobei das ganze auch einfacher als

    cmd < eingabe.txt &> ausgabe.log

    geschrieben werden kann.

  • Fehlermeldungen und Ausgaben an „Dateiname“ anhängen:
    Befehl > Dateiname 2>&1 
  • Ausgaben und Fehlermeldungen an „Dateiname“ anhängen:
    Befehl > Dateiname 2<&1 

Den Begriff Returncode bzw. Exitlevel vorher: Rückgabe von „0“ an das Betriebssystem heißt Erfolg, alles andere (Returncode ≠ 0) sind Fehler.

Schema Wirkung
cmd1 | cmd2 Pipe: Die Standardausgabe des ersten Befehls (cmd1) ist die Eingabe des zweiten Befehls.
cmd1; cmd 2 Einfache Verküpfung: cmd2 wird gestartet wenn cmd1 beendet ist (egal ob erfolgreich oder nicht).
cmd1 & cmd2 cmd1 wird im Hintergrund ausgeführt, während dessen wir schon cmd2 ausgeführt
cmd1 && cmd2 cmd2 wird nur ausgeführt wenn cmd1 fehlerfrei beendet wurde (Returncode = 0)
cmd1 || cmd2 cmd2 wird nur ausgeführt wenn cmd1 fehlerhaft beendet wurde (Returncode ≠ 0)

Der Befehl test (oft nur über die Aliase der eckigen Klammern [ ] benutzt) prüft verschiedene Bedingungen ab und liefert einen Boolean-Rückgabewert (true oder false) zurück.

Beispiel:

if [ zeichenkette1 == zeichenkette2 ]
then
   echo "Zeichenketten sind gleich."
else
   echo "Zeichenketten sind ungleich."
fi

Auch reguläre Ausdrücke sind möglich:

[[ "string" =~ pattern ]]
Tests für Dateien
Syntax (name = Dateiname) testet was?
-d name name ist ein Verzeichnis
if [ ! "`ls -A $verz`" ]
then
        echo "leer!"
fi
Verzeichnis leer?
-e name name ist eine Datei
-f name name ist eine reguläre Datei
-L name name ist ein symbolischer Link
-r name name existiert und ist lesbar
-w name name existiert und ist schreibbar
-x name name existiert und ist ausführbar
-s name name existiert und hat eine von Null unterschiedliche Größe
name1 -nt name2 name1 ist jünger als name2
name1 -ot name2 name1 ist älter als name2
Tests für Zeichenketten (Strings)
Syntax testet was?
s1 == s2 s1 und s2 sind gleich
s1 != s2 s1 und s2 sind ungleich
-z s1 s1 hat Länge Null
-n s1 s1 hat Länge ungleich Null
nummerische Tests, für ganzzahlige (Integer)
Syntax testet was?
a -eq b a und b sind gleich
a -ne b a und b sind ungleich
a -gt b a größer als b
a -ge b a größer-gleich als b
a -lt b a kleiner als b
a -le b a kleiner-gleich b
Kombinationen und Negationen (Umkehrungen)
SyntaxWirkung
test1 -a test2 test1 und test2 sind wahr
test1 -o test2 test1 oder test2 sind wahr
! Bedingung Testnegationen: Bedingung ist falsch
\( Bedingung \) Verkettung bzw. Gruppieren von Bedingungen: Backslash \ schützt die Klammern

Die Ausgabe von Programmen in einer Variable speichern:

Datum=`date`

oder besser (weil verschachtelbar!):

Datum=$(date)
if [ -z $1 ]; then
 echo "empty parameter!"
 echo "usage: $0 [Parameter]"
 exit
fi
Code

oder leicht einfacher (und umgedreht):

if [ $1 ]; then
 CODE
else
 echo "empty parameter!"
 echo "Usage: $0 [Parameter]"
fi
if [ "`id -u`" -eq 0 ]; then
 echo you are root!
else
 echo you are not root!
fi

Posix-kompatibel:

echo -n "Is this a good question (y/n)? "
read answer
if [ "$answer" != "${answer#[Yy]}" ] ;then
    echo Yes
else
    echo No
fi

Bash:

echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) make install; break;;
        No ) exit;;
    esac
done

How do I prompt for Yes/No/Cancel input in a Linux shell script?

Skripts sollten bei Aufruf über cron nicht unnötig Statusmeldungen erzeugen:

if [ -z "$PS1" ]; then
    echo This shell is not interactive.
else
    echo This shell is interactive.
fi

Einfache Dateien können mit „echo Inhalt > Datei“ erzeugt werden, was aber wenn komplexe Konfigurationsdateien erzeugt werden müssen?

cat > "Dateiname" << EOF
  <Directory />
        AllowOverride AuthConfig FileInfo Limit Indexes
        Order allow,deny
        allow from all
  </Directory>
EOF

kopfgesteuert: wird nur ausgeführt wenn Bedingung erfüllt.

von 1.. bis 10 zählen:

#!/bin/bash
i=1
while [ $i -le 10 ]
do
  echo $i
  let i=$i+1 #nur bash
  # i=`expr $i + 1` # universal
done

oder als for-Schleife:

for i in {0..10}; do echo $i; done

Fußgesteuert: wird mindestens einmal ausgeführt und anschließend nur wenn Bedingung erfüllt.

von 1.. bis 10 zählen:

#!/bin/bash
i=1
until [ $i -gt 10 ]
do
  echo $i
  let i=$i+1 #nur bash
  # i=`expr $i + 1` # universal
done
for zeile in $(cat listendatei.txt); do
 echo $zeile
done

bzw. diese Alternativlösung wenn die Zeilen auch Leerzeichen enthalten könnten:

while read -r zeile ; do
   echo "$zeile"
done < listendatei.txt

sed:

  • vorne:
    sed 's/^[[:blank:]]*//'
  • hinten:
    sed 's/[[:blank:]]*$//'
  • vorne+hinten:
    sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'

tr (mehr als ein Leerzeichen):

  • tr -s ' '

bash-only-Lösung:

  • vorne:
    shopt -s extglob
    echo ${text##+([[:space:]])}
  • hinten:
    shopt -s extglob
    echo ${text%%+([[:space:]])}
  • alle Leerzeichen entfernen:
    echo ${text//[[:space:]]}
#!/bin/bash
 
set -e -o pipefail
 
function cleanup {
  EXIT_CODE=$?
  set +e # disable termination on error
  rm "$tempfile"
  exit $EXIT_CODE
}
trap cleanup EXIT

Quelle siehe auch: Fehlerbehandlung in Shellskripten.

Fehler aufgetreten (Exit-Code ungleich 0)

if [ $? -ne 0 ]
then
  echo Fehler aufgetreten
  exit 1
else
  Code
fi

Aus einem Pfad bekommt man mit

  • basename den Dateinamen und mit
  • dirname den Verzeichnispfad heraus.

Andere Möglichkeiten

  • nur den Dateinamen (ohne Erweiterung):
    echo "$DATEINAME" | cut -d. -f1
  • nur die Erweiterung:
    echo $DATEINAME | awk -F . '{print $NF}'
  • pro Aufruf eine Ebene wegnehmen (bei mehreren Punkten im Dateinamen):
    • 1 Ebene:
      echo "$DATEINAME" | sed s/\.[^\.]*$//
    • 2 Ebenen (usw.):
      echo "$DATEINAME" | sed s/\.[^\.]*$// | sed s/\.[^\.]*$//

Anwendungsbeispiel: Vor der Erweiterung etwas einfügen.

a="Dateiname.ext"
xclude_ext=`echo "$DATEINAME" | cut -d. -f1`
ext=`echo $DATEINAME | awk -F . '{print $NF}'`
mv "$a" "$xclude_ext"-Zwischentext."$ext"

# Kommentarzeilen entfernen: sed /^#/d Dateiname.txt

Leerzeilen: sed /^$/d Dateiname.txt

 # Doppelter Zeilenvorschub
 sed G

 # Doppelter Zeilenabstand für Dateien, die Leerzeilen enthalten.
 # Die Ausgabe sollte keine zwei aufeinander folgenden Leerzeilen enthalten.
 sed '/^$/d;G'

 # Dreifacher Zeilenvorschub
 sed 'G;G'

 # Doppelter Zeilenvorschub rückgängig machen
 # (Annahme: jede zweite Zeile ist leer)
 sed 'n;d'

 # Füge eine Leerzeile über jeder Zeile ein, die "regex" enthält
 sed '/regex/{x;p;x;}'

 # Füge eine Leerzeile unter jeder Zeile ein, die "regex" enthält
 sed '/regex/G'

 # Füge eine Leerzeile über und unter jeder Zeile ein, die "regex" enthält
 sed '/regex/{x;p;x;G;}'

Nummerierung

 # Nummeriere alle Zeilen (linksbündig). Der Tabulator anstelle von Leerzeichen
 # erhält den Rand. (siehe auch die Bemerkung zu '\t' am Ende dieser Datei)
 sed = filename | sed 'N;s/\n/\t/'

 # Nummeriere alle Zeilen (Zahl rechtsbündig in linker Spalte)
 sed = filename | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'

 # Nummeriere alle Zeilen, aber die Nummern von Leerzeilen werden nicht ausgegeben.
 sed '/./=' filename | sed '/./N; s/\n/ /'

 # Zeilen zählen (Nachahmung von "wc -l")
 sed -n '$='

TEXT UMWANDLUNG UND ERSETZUNG:

 # IN EINER UNIX UMGEBUNG: Wandle DOS Zeilenvorschübe (CR/LF) in das Unix-Format.
 sed 's/.$//'               # Annahme: Alle Zeilen enden mit CR/LF
 sed 's/^M$//'              # Bei bash/tcsh: Ctrl-V dann Ctrl-M
 sed 's/\x0D$//'            # für ssed, gsed 3.02.80 oder neuere Versionen

 # IN EINER UNIX UMGEBUNG: Wandle Unix Zeilenvorschübe (LF) in das DOS-Format.
 sed "s/$/`echo -e \\\r`/"            # ksh
 sed 's/$'"/`echo \\\r`/"             # bash
 sed "s/$/`echo \\\r`/"               # zsh
 sed 's/$/\r/'                        # gsed 3.02.80 oder neuere Versionen

 # IN EINER DOS UMGEBUNG: Wandle Unix Zeilenvorschübe (LF) in das DOS-Format.
 sed "s/$//"                          # Möglichkeit 1
 sed -n p                             # Möglichkeit 2

 # IN EINER DOS UMGEBUNG: Wandle DOS Zeilenvorschübe (CR/LF) in das Unix-Format.
 # Die kann mit mit der UnxUtils Version von sed, Version 4.0.7 oder neuer
 # gemacht werden. Die UnxUtils Version von sed kann durch die zusätzliche
 # "--text" Option bestimmt werden, die beim Aufruf mit "--help" angezeigt wird.
 # Ansonsten kann die Umwandlung von DOS-Zeilenvorschüben in UNIX-Zeilenvorschübe
 # nicht mit sed unter DOS vorgenommen werden. Benutzen Sie stattdessen "tr".
 sed "s/\r//" infile >outfile         # UnxUtils sed v4.0.7 oder neuer
 tr -d \r <infile >outfile            # GNU tr Version 1.22 oder neuer

 # Lösche alle Einrückungen (Leerzeichen, Tabulatoren) vom Anfang jeder Zeile
 # Richtet alle Zeilen linksbündig aus.
 sed 's/^[ \t]*//'                    # (siehe auch die Bemerkung zu '\t' am Ende dieser Datei)

 # Lösche unsichtbare Zeichen (Leerzeichen, Tabulatoren) vom Ende aller Zeilen
 sed 's/[ \t]*$//'                    # (siehe auch die Bemerkung zu '\t' am Ende dieser Datei)

 # Lösche unsichtbare Zeichen sowohl am Anfang als auch am Ende jeder Zeile
 sed 's/^[ \t]*//;s/[ \t]*$//'

 # Füge 5 Leerzeichen am Anfang jeder Zeile ein. (Einrückung)
 sed 's/^/     /'

 # Alle Zeilen rechtsbündig ausrichten (Spaltenbreite: 79 Zeichen)
 sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # set at 78 plus 1 space

 # Zentriere alle Zeilen in einer 79-Zeichen breiten Spalte.
 # Bei Methode 1 bleiben Leerzeichen am Zeilenanfang und -ende erhalten.
 # Bei Methode 2 werden Leerzeichen am Zeilenanfang gelöscht und es
 # folgen keine Leerzeichen am Zeilenende.
 sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # Möglichkeit 1
 sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # Möglichkeit 2

 # Ersetze (Suchen und Ersetzen) "foo" mit "bar" in jeder Zeile
 sed 's/foo/bar/'                    # Ersetzt nur das 1. Vorkommen pro Zeile
 sed 's/foo/bar/4'                   # Ersetzt nur das 4. Vorkommen pro Zeile
 sed 's/foo/bar/g'                   # Ersetzt ALLE Vorkommen von "foo" mit "bar"
 sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # Ersetzt nur das vorletzte Vorkommen pro Zeile
 sed 's/\(.*\)foo/\1bar/'            # Ersetzt nur das letzte Vorkommen pro Zeile


 # Ersetze "foo" mit "bar" NUR in Zeilen die "baz" enthalten
 sed '/baz/s/foo/bar/g'

 # Ersetze "foo" mit "bar" AUSSER in Zeilen die "baz" enthalten
 sed '/baz/!s/foo/bar/g'

 # Ersetze "scarlet", "ruby" oder "puce" mit "red"
 sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'   # Die meisten seds
 gsed 's/scarlet\|ruby\|puce/red/g'                # Nur GNU sed 

 # Kehre die Reihenfolge der Zeilen um (entspricht "tac")
 # Bug/Feature in HHsed v1.5 löscht hierbei Leerzeilen
 sed '1!G;h;$!d'               # Möglichkeit 1
 sed -n '1!G;h;$p'             # Möglichkeit 2

 # Kehre die Reihenfolge der Buchstaben innerhalb jeder Zeile um (entspricht "rev")
 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

 # Füge Zeilenpaare nebeneinander zusammen (entspricht "paste")
 sed '$!N;s/\n/ /'

 # Falls eine Zeile mit einem Rückwärtsstrich "\" endet, füge die nächste hinzu.
 sed -e :a -e '/\\$/N; s/\\\n//; ta'

 # Falls eine Zeile mit einem Gleichheitszeichen "=" beginnt, 
 # füge die vorhergehende hinzu und ersetzt das "=" mit einem Leerzeichen.
 sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

 # Füge Kommas in Zahlenfolgen ein. Aus "1234567" wird "1,234,567"
 gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'                     # GNU sed
 sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'  # Andere seds

 # Füge Kommas in Zahlenfolgen mit Dezimalpunkt und Vorzeichen ein.  (GNU sed)
 gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'

 # Füge alle 5 Zeilen eine Leerzeile ein. (Nach 5, 10, 15, 20,... Zeilen)
 gsed '0~5G'                  # GNU sed
 sed 'n;n;n;n;G;'             # andere seds

DRUCKEN AUSGEWÄHLTER ZEILEN:

 # Ausgabe der ersten 10 Zeilen einer Datei (wie "head")
 sed 10q

 # Ausgabe der ersten Zeilen einer Datei (wie "head -1")
 sed q

 # Ausgabe der letzten 10 Zeilen einer Datei (wie "tail")
 sed -e :a -e '$q;N;11,$D;ba'

 # Ausgabe der letzten beiden Zeilen einer Datei (wie "tail -2")
 sed '$!N;$!D'

 # Ausgabe der letzten Zeilen einer Datei (wie "tail -1")
 sed '$!d'                    # Möglichkeit 1
 sed -n '$p'                  # Möglichkeit 2

 # Ausgabe der vorletzten Zeile einer Datei
 sed -e '$!{h;d;}' -e x              # Bei einzeiligen Dateien wird eine Leerzeile ausgegeben
 sed -e '1{$q;}' -e '$!{h;d;}' -e x  # Bei einzeiligen Dateien wird die Zeile ausgegeben
 sed -e '1{$d;}' -e '$!{h;d;}' -e x  # Bei einzeiligen Dateien wird nichts ausgegeben

 # Ausgabe der Zeilen, die durch den Regulären Ausdruck (Regex) definiert sind (wie "grep")
 sed -n '/regexp/p'           # Möglichkeit 1
 sed '/regexp/!d'             # Möglichkeit 2

 # Ausgabe der Zeilen, die den Reguläre Ausdruck NICHT erfüllen (wie "grep -v")
 sed -n '/regexp/!p'          # Möglichkeit 1, entspricht obiger Lösung
 sed '/regexp/d'              # Möglichkeit 2, Einfacher Syntax

 # Ausgabe der Zeile direkt oberhalb des Regex, jedoch nicht die Zeile 
 # die den Regex erfüllt.
 sed -n '/regexp/{g;1!p;};h'

 # Ausgabe der Zeile direkt unterhalb des Regex, jedoch nicht die Zeile 
 # die den Regex erfüllt.
 sed -n '/regexp/{n;p;}'

 # Ausgabe eine umgebende Zeile vor und nach der Regex, mit Angabe
 # der Zeilennummer der Zeile, die den Regex erfüllt. (ähnlich "grep -A1 -B1")
 sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

 # Suche nach AAA und BBB und CCC (in beliebiger Reihenfolge)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'

 # Suche nach AAA und BBB und CCC (in vorgegebener Reihenfolge)
 sed '/AAA.*BBB.*CCC/!d'

 # Suche nach AAA oder BBB oder CCC (wie "egrep")
 sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # die meisten seds
 gsed '/AAA\|BBB\|CCC/!d'                        # GNU sed

 # Ausgabe des Absatzes falls dieser AAA enthält (Leerzeilen trennen Absätze)
 # Für HHsed v1.5 muss 'G;' nach 'x;' eingefügt werden.
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

 # Ausgabe des Absatzes falls dieser AAA, BBB und CCC enthält. (Reihenfolge egal)
 # Für HHsed v1.5 muss 'G;' nach 'x;' eingefügt werden.
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

 # Ausgabe des Absatzes falls dieser AAA, BBB oder CCC enthält.
 # Für HHsed v1.5 muss 'G;' nach 'x;' eingefügt werden.
 sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
 gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'         # nur GNU sed 

 # Ausgabe der Zeilen die 65 Zeichen lang oder länger sind
 sed -n '/^.\{65\}/p'

 # Ausgabe der Zeilen die kürzer als 65 Zeichen sind
 sed -n '/^.\{65\}/!p'        # Möglichkeit 1, entspricht obiger Lösung
 sed '/^.\{65\}/d'            # Möglichkeit 2, eifacherer Syntax

 # Ausgabe der Datei ab dem regulären Ausdruck bis zum Ende
 sed -n '/regexp/,$p'

 # Ausgabe eines Abschnittes der Datei, der durch Zeilennummern definiert ist
 # (hier: 8-12, inklusive)
 sed -n '8,12p'               # Möglichkeit 1
 sed '8,12!d'                 # Möglichkeit 2

 # Ausgabe von Zeile 52
 sed -n '52p'                 # Möglichkeit 1
 sed '52!d'                   # Möglichkeit 2
 sed '52q;d'                  # Möglichkeit 3, effizient für große Dateien

 # Ausgabe jeder 7. Zeile - beginnend bei Zeile 3
 gsed -n '3~7p'               # nur GNU sed
 sed -n '3,${p;n;n;n;n;n;n;}' # andere seds

 # Ausgabe des Teils der Datei, der zwischen den regulären Ausdrücken ist (inklusive der Regexs)
 sed -n '/Iowa/,/Montana/p'             # berücksichtigt die Groß/Kleinschreibung

LÖSCHUNG BESTIMMTER ZEILEN:

 # Ausgabe der Datei, AUSSER dem Teil, der zwischen den regulären Ausdrücken ist
 sed '/Iowa/,/Montana/d'

 # Löschung von aufeinander folgenden, identischen Zeilen (wie "uniq").
 # Die erste Zeile in einer Folge von Duplikaten wird ausgegeben, der Rest gelöscht.
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # Lösche identische, nicht aufeinander folgende Zeilen einer Datei.
 # Achten Sie darauf nicht die Buffer-größe des "Hold-spaces" zu überschreiten oder benutzen Sie GNU sed.
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

 # Löscht alle Zeilen außer Duplikate (wie "uniq -d").
 sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'

 # Löscht die ersten 10 Zeilen einer Datei
 sed '1,10d'

 # Löscht die letzte Zeile einer Datei
 sed '$d'

 # Löscht die zwei letzten Zeilen einer Datei
 sed 'N;$!P;$!D;$d'

 # Löscht die 10 letzten Zeilen einer Datei
 sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # Möglichkeit 1
 sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # Möglichkeit 2

 # Lösche jede 8. Zeile
 gsed '0~8d'                           # nur GNU sed
 sed 'n;n;n;n;n;n;n;d;'                # andere seds

 # Lösche Zeilen die die Regex erfüllen
 sed '/pattern/d'

 # Lösche ALLE Leerzeilen aus einer Datei (wie "grep '.' ")
 sed '/^$/d'                           # Möglichkeit 1
 sed '/./!d'                           # Möglichkeit 2

 # Lösche alle AUFEINANDER FOLGENDEN Leerzeilen außer der ersten;
 # außerdem, lösche alle Leerzeilen am Anfang und am Ende der Datei 
 # (Wie "cat -s")
 sed '/./,/^$/!d'          # Möglichkeit 1, lässt 0 Leerzeilen am Anfang, 1 am Ende der Datei
 sed '/^$/N;/\n$/D'        # Möglichkeit 2, lässt 1 Leerzeilen am Anfang, 0 am Ende der Datei

 # Lösche alle AUFEINANDER FOLGENDEN Leerzeilen, außer die ersten 2:
 sed '/^$/N;/\n$/N;//D'

 # Lösche alle Leerzeilen am Anfang einer Datei
 sed '/./,$!d'

 # Lösche alle Leerzeilen am Ende einer Datei
 sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # funktioniert bei allen seds
 sed -e :a -e '/^\n*$/N;/\n$/ba'        # ditto, außer bei gsed 3.02.*

 # Lösche die letzte Zeile jedes Absatzes
 sed -n '/^$/{p;h;};/./{x;/./p;}'

SPEZIELLE EINSATZGEBIETE:

 # Entferne nroff "overstrikes" (char, Rückschritt) aus Man-Seiten.
 # Die 'echo' Anweisung braucht eventuell die Option -e für die Unix System V shell oder bash.
 sed "s/.`echo \\\b`//g"    # Doppelte Anfürungszeichen werden in Unix-Umgebungen benötigt.
 sed 's/.^H//g'             # In bash/tcsh, Ctrl-V und dann Ctrl-H drücken
 sed 's/.\x08//g'           # Hex-Angabe für sed 1.5, GNU sed, ssed

 # nur die Usenet/E-Mail Kopfzeilen
 sed '/^$/q'                # Löscht alles nach der ersten Leerzeile

 # nur die Usenet/E-Mail Nachrichtentext
 sed '1,/^$/d'              # Löscht alles bis zur ersten Leerzeile

 # Die Betreffzeile einer E-Mail, aber ohne das "Subject: " am Zeilenanfang
 sed '/^Subject: */!d; s///;q'

 # Die Antwortadresse einer E-Mail
 sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

 # Extrahiert die E-Mail-Adresse aus der Antwortadresse des vorherigen Scripts
 sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

 # Ein Größer-Zeichen an jedem Zeilenanfang einfügen (Nachricht zitieren)
 sed 's/^/> /'

 # Größerzeichen am Zeilananfang löschen (Macht vorheriges script rückgängig)
 sed 's/^> //'

 # Entferne die meisten HTML-Auszeichnungen (inklusive die über mehrere Zeilen)
 sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

 # Multi-part uuencodierte Binärdateien auspacken
 # und fehlerhafte Kopfzeilen entfernen, so dass nur die uuencodierten Daten 
 # übrig bleiben.
 # Die übergebenen Dateien müssen in der richtigen Reihenfolge sein.
 # Möglichkeit 1 kann auf der Kommandozeile ausgeführt werden,
 # Möglichkeit 2 kann als Unix-Shell-Script ausgeführt werden. (Basierend auf einem Script von Rahul Dhesi)
 sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode   # Möglichkeit 1
 sed '/^end/,/^begin/d' "$@" | uudecode                    # Möglichkeit 2

 # Sortiere die Absätze der Datei alphabetisch. Absätze werden durch Leerzeilen getrennt.
 # GNU sed benutzt \v als vertikale Tabulatoren (Alternativ kann auch jedes andere, 
 # eindeutige Zeichen verwendet werden)
 sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
 gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'

 # Komprimiere jede .TXT-Datei einzeln mit zip, lösche die Quelldatei
 # und benenne jede ZIP-Datei mit dem Namen der TXT-Datei ohne .TXT
 # (unter DOS: Der Befehl "dir /b" gibt die reinen Dateinamen in Großbuchstaben zurück)
 echo @echo off >zipup.bat
 dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

TYPISCHE BEFEHLSZEILEN: Sed nimmt eine oder mehrere Bearbeitungsbefehle
entgegen und wendet diese, in der entsprechenden Reihenfolge auf jede
Zeile der Eingahe an. Nachdem alle Befehle auf die erste Zeile angewendet
wurden, wird diese ausgegeben, und die zweite Zeile wird zur Bearbeitung
entgegengenommen. Der Kreislauf wiederholt sich. Die vorhergehenden Beispiele
gehen davon aus, dass die Eingaben von der Standarteingabe (STDIN) kommen (d.h. z.B.
die Tastatur, bzw. i.d.R. wird die Eingabe von einer Pipe kommen).
Ein oderer mehrere Dateinamen können an die Befehlszeile angehängt werden,
fallt die Eingabe nicht von STDIN kommt. Die Ausgaben werden an die 
Standarteingabe geschickt, d.h. i.d.R. auf dem Bildschirm ausgegeben.
Daher gilt:

 cat filename | sed '10q'        # Benutzt die "Pipe" zur Eingabe
 sed '10q' filename              # gleicher Effekt, spart das unnötige "cat"
 sed '10q' filename > newfile    # Leitet die Ausgabe um ins Dateisystem

Weitere Erklärungen des Sysntax, inklusive der Möglichkeit Befehle
von einer Datei statt von der Befehlszeile zu benutzen sind in "sed &
awk, 2nd Edition," von Dale Dougherty und Arnold Robbins (O'Reilly,
1997; http://www.ora.com), "UNIX Text Processing," von Dale Dougherty
und Tim O'Reilly (Hayden Books, 1987) oder in den Anleitungen von Mike Arst
die als U-SEDIT2.ZIP au vielen Seiten zum Download bereit stehen zu finden.

Um alle Möglichkeiten von sed zu nutzen, muss man Reguläre Ausdrücke
verstehen. Hierfür können folgende Bücher herangezogen werden:
"Mastering Regular Expressions" von Jeffrey Friedl (O'Reilly, 1997).
Die Manual-Seiten ("man") auf Unix-Systemen können auch hilfreich sein.
("man sed", "man regexp", oder der Abschnitt über Reguläre Ausdrücke in
"man ed"), aber einige dieser Seiten sind für ihren Schwierigkeitsgrad
bekannt. Sie sind nicht als Einführung für neue Sed- oder Regex-Benutzer
geschrieben, sondern als Referenz für diejenigen, die diese Werkzeuge 
bereits beherrschen.

BENUTZUNG VON HOCHKOMMAS:
Die angeführten Beispiele schließen die Anweisungen in einfache 
Anführungszeichen ('...') anstatt der doppelten ("...") ein, da
sed typischerweise in einer Unix-Umgebung zur Anwendung kommt.
Einfache Anführungszeichen hindern die Unix-Shell (Kommandozeile)
daran, das Dollarzeichen ($) und die umgekehrten Hochkommas (`...`)
auszuwerten, wie dies bei der verwendung von doppelten Anführungszeichen 
("...") der Fall wäre.
Benutzer der "csh" Shell und deren Weiterentwicklungen müssen ausserdem
trotz verwendung von einfachen Anführungszeichen alle Ausrufezeichen (!) 
mit einem Rückwärtsstrich schützen (z.B. "\!") um die Beispiele korrekt 
ausführen zu können.
DOS-Versionen von sed benötigen allesamt doppelte Anführungszeichen ("...")
um die Befehle herum.

DIE BENUTZUNG VON '\t' IN SED-SCRIPTEN:
Der Deutlichkeit halber haben wir in diesem Dokument die Zeichenfolge '\t'
benutzt, um das Tabulatorzeichen (0x09) darzustellen. Die meisen Versionen
von sed kennen jedoch diese Darstellung nicht.
Bei der Eingabe der Befehle muss '\t' durch drücken der Tabulatortaste 
eingegeben werden. '\t' wird von awk, perl, HHsed, sedmod, und GNU sed
v3.02.80 in regulären Ausdrücken als Tabulator anerkannt.

VERSIONEN VON SED:
Die unterschiedlichen sed-versionen haben unterschied und man muss auch
mit leichten Unterschieden im Syntax rechnen. Besonders die Benutzung von
Marken (:name) oder Verzweigungen (b,t) innerhalb von Kommandos (nicht an
deren Ende) werden von vielen Versionen nicht unterstützt.
Wir haben eine Schreibweise gewählt, die sich mit den meisten Versionen
von sed benutzen lässt, auch wenn die beliebten GNU-Versionen von sed eine
elegantere Schreibweise erlauben würden.
Wem man einen ziemlich langen Befehl wie den folgenden sieht:

   sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

ist es gut zu wissen, dass man diesen mit GNU-sed zu folgendem kürzen kann:

   sed '/AAA/b;/BBB/b;/CCC/b;d'      # oder sogar
   sed '/AAA\|BBB\|CCC/b;d'

Ausserdem ist zu beachten, dass obwohl viele Versionen von sed einen Befehl 
wie "/one/ s/RE1/RE2/" erlauben, einige "/one/! s/RE1/RE2/" NICHT erlauben,
was ein Leerzeichen vor dem 's' enthält. Bei der Eingabe der Befehle muss hier
das Leerzeichen weggelassen werden.

GESCHWINDIGKEITSOPTIMIERUNG:
Falls die ausfürungsgeschwindigkeit wegen großen Dateien oder langsamen CPUs
bzw. Festplatten erhöht werden muss, können Ersetzungen beschleunigt werden,
indem der gesuchte Ausdruck vor dem "s/.../.../" genannt wird. Es gilt:

   sed 's/foo/bar/g' filename         # Normales Suchen & Ersetzen
   sed '/foo/ s/foo/bar/g' filename   # Schnellere Version
   sed '/foo/ s//bar/g' filename      # sed Kurzschreibweise

Wenn bei der Auswahl oder Löschung von Zeilen nur Zeilen aus dem Dateianfang
ausgegeben werden sollen, verkürzt bei großen Dateien ein "quit" Befehl (q)
die Bearbeitungszeit erheblich. Daher:

   sed -n '45,50p' filename           # Ausgabe der Zeilen 45-50 einer Datei
   sed -n '51q;45,50p' filename       # dito, aber biel schneller.

Quelle (Original)

In einigen Fällen ist es nötig den Benutzer eine Auswahl treffen zu lassen. Dazu bieten sich einige Programme an, zenity ist sicherlich eine der besseren Programmen; es basiert auf dem GTK+-Toolkit und zeigt die Texte lokalisiert an (siehe Screenshot).

Anzeigebeispiel (Siehe auch: A complete zenity dialog examples #1 und #2 und das Zenity-Handbuch z.B. zum Thema Fortschrittsanzeige-Dialog):

Zenity Screenshot

Die Auswertung der Antwort(en) ist relativ simpel:

  • ausgewählte Optionen werden komplette als Text zurückgegeben, wenn Mehrfachauswahlen zugelassen sind, dann sind diese durch ein „|“-Symbol getrennt. Um in diesem Fall die Antworten besser auswerten zu können, könnte man durch anfügen von --separator=„\n“ als Trenner einen Zeilenumbruch nehmen und dann eine for-Schleife über alle Antworten laufen lassen:
    for dev in $answer
    do
    	echo "answer is $dev"
    done
  • OK ist Errorlevel 0 (Variable $? prüfen)
  • Cancel ist Errorlevel 1 (Variable $? prüfen)
answer=`zenity --title="main menu" --width=300 --height=200 --list  --radiolist  --column "select" --column "choice" TRUE choice1 FALSE choice2 FALSE "choice3 with more text"`
if [ $? -eq 1 ]; then
	echo "cancel pressed"
	exit
else
	echo "OK pressed"
	case "$answer" in
	choice1)
 
		echo "choice1"
		;;
	choice2)
		echo "choice2"
		;;
	choice3)
		echo "choice3"
		;;
	*)
		echo "case $answer not implemented yet."
		;;
	esac
fi

konkrete Programme

  • Checkmd5: md5-Summen von vielen Dateien mit einzelnen md5-Prüfsummendateien
  • Rename (Wahrscheinlich das meist-vermisste bei Umsteigern)
  • Rename2 noch ein Rename, sollte ich vielleicht in Par2 check+unpack einbauen um die vol-Dateien automatisch umzubenennen!

alt.bin.repair - umfangreiches Shellscript zum Prüfen und entpacken von .par2-sets aus dem usenet.

  • encode: zum enkodieren von Videos (Aufruf ./encode DATEI)
  • vidcut: zum Extrahieren einer Sequenz aus einem Video
  • vmerge: um mehrere Videos zusammenzufügen

CLI Magic: Video conversion with mencoder