Benutzer-Werkzeuge

Webseiten-Werkzeuge


awk

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
awk [2020-03-12 10:44:34] – [Zahlen formatiert ausgeben] manfredawk [2024-07-31 00:17:54] (aktuell) – [Runden] manfred
Zeile 1: Zeile 1:
 +====== AWK ======
 +
 +**AWK**: Abkürzung, die aus den Anfangsbuchstaben der Nachnamen der drei "Väter" der Sprache AWK besteht: Al **A**ho, Peter **W**einberger, Brian **K**ernighan
 +
 +  * **[[https://de.wikibooks.org/wiki/Awk:_Grundlagen:_Aktionen]]**
 +  * [[http://www.net-braun.de/etc/awk-kurs.htm]]
 +  * [[http://mikiwiki.org/wiki/awk/Einstieg_in_awk]]
 +  * [[http://www-e.uni-magdeburg.de/urzs/awk/awk.shtml]]
 +  * [[http://www.thomashertweck.de/sedawk.html]]
 +  * [[http://www.clug.de/vortraege/awk/index.html]]
 +  * [[http://www.christinewolfinger.de/Seminare/15AWKF.pdf]]
 +  * [[http://www.unix-manuals.com/refs/awk/awk.htm]]
 +  * [[http://www.linupedia.org/opensuse/Awk#Die_Aktion]]
 +  * **[[https://www.ostc.de/awk.pdf]]**
 +  * **[[https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html]]**
 +
 +  > echo -e "1\n2\n3"
 +  1
 +  2
 +  3
 +  
 +  > echo -e "1\n2\n3" | awk 'NR==2'
 +  2
 +  
 +  > echo "1 2 3" | awk '{print $2}'
 +  2
 +  
 +  > echo "1:2:3" | awk -F':' '{print $2}'
 +  2
 +  
 +  > echo "foooobazbarrrrr" | awk '{print $1}'
 +  foooobazbarrrrr
 +  
 +  > echo "foooobazbarrrrr" | awk '{ match($0, /(fo+).+(bar*)/, arr); print arr[1], arr[2] }'
 +  foooo barrrrr
 +  
 +
 +
 +==== Runden ====
 +
 +echtes runden mit awk:
 +  > echo "5.56" | awk '{printf "%.1f\n", $1}'
 +  5.6
 +  > echo "5.56" | awk '{printf "%.0f\n", $1}'
 +  6
 +
 +abrunden mit awk:
 +  > echo "5.56" | awk '{printf("%u\n", $1)}'
 +  5
 +
 +Zahlen mit fester Länge ausgeben:
 +  > echo "5.56" | awk '{printf("%.8u\n", $1)}'
 +  00000005
 +
 +
 +==== Pi ====
 +
 +  > echo | awk '{print 4 * atan2(1,1)}'
 +  3.14159
 +  
 +  # "AWK" ist nur bis zur 15. Nachkommastelle genau
 +  > echo | awk '{printf "%.15f\n", 4 * atan2(1,1)}'
 +  3.141592653589793
 +
 +
 +==== Zahlen summieren ====
 +
 +Zusammenzählen aller Werte in der 1. Spalte ("$1"):
 +  # awk '{zwischenwert=$1;summe+=zwischenwert}END{print "Gesamtwert:",summe}'
 +  # awk '{zwischenwert=$1; summe += zwischenwert } END { print "Gesamtwert:", summe }'
 +  # awk '{zwischenwert=$1; summe += zwischenwert } END { printf("%li", summe)}'
 +  # awk '{z=$1;s+=z}END{printf("%li", s)}'
 +  # awk '{z=$1;s+=z}END{print s}'
 +  # awk '{z=$1;s+=z}END{printf("%.2f\n",s/1024^3)}'
 +
 +Durchschnitt aller Werte der letzten Spalte:
 +  # cat ... | nl | awk '{ zwischenwert=$NF; summe += zwischenwert } END { print summe/$1 }'
 +
 +
 +==== Schleife ====
 +
 +  * [[https://im-coder.com/wie-awk-verwenden-um-spalten-in-einer-schleife.html]]
 +  * [[https://www-user.tu-chemnitz.de/~hot/unix_linux_werkzeugkasten/awk.html]]
 +
 +  # echo "7" | awk '{for (i=1;i<=$1;i++) print i }'
 +  1
 +  2
 +  3
 +  4
 +  5
 +  6
 +  7
 +
 +
 +==== Wurzel ziehen ====
 +
 +  Wurzel aus 9
 +  > echo "9" | awk '{print sqrt($1)}'
 +  3
 +
 +  > echo "10 1" | awk '{print sqrt($1-$2)}'
 +  3
 +
 +5. Wurzel aus 4 ([[https://frageit.de/questions/42775094/nth-root-in-bash]]):
 +  > awk 'BEGIN { print (4 ** (1.0 / 5)) }'
 +  1.31951
 +  
 +  > awk 'BEGIN { print (ARGV[2] ** (1.0 / ARGV[1])) }' 5 4
 +  1.31951
 +
 +
 +==== Logarithmus ====
 +
 +natürlicher Logarithmus aus 5:
 +  > echo "5" | awk '{print log($1)}'
 +  1.60944
 +
 +natürlicher Logarithmus aus 20:
 +  > echo "20" | awk '{print log($1)}'
 +  2.99573
 +
 +dezimaler Logarithmus 1000:
 +  > echo "1000" | awk '{print log($1)/log(10)}'
 +  3
 +
 +binärer Logarithmus aus 8: 
 +  > echo "8" | awk '{print log($1)/log(2)}'
 +  3
 +
 +
 +==== IF-Verzweigung ====
 +
 +Mit Alphanumerischen Zeichen:
 +  # echo 'WPA2' | awk '{proto="nix"; if ($1 == "WPA") proto="WPA"; if ($1 == "WPA2") proto="RSN"; print proto}'
 +  RSN
 +
 +die "if"-Anweisung von AWK kann sogar mit Kommastellen umgehen:
 +  # echo "1.5" | awk '{if ($1 < 3) GR="gross" ; if ($1 < 2) GR="mittel" ; if ($1 < 1) GR="klein" ; print $1"="GR}'
 +  1.5=mittel
 +
 +  # echo "1.5" | awk '{if ($1 < 3) GR=3 ; if ($1 < 2) GR=2 ; if ($1 < 1) GR=1 ; print GR}'
 +  2
 +
 +  # echo "2" | awk '{if ($1 == 1) GR="klein" ; if ($1 == 2) GR="mittel" ; if ($1 == 3) GR="gross" ; print GR}'
 +  mittel
 +
 +
 +=== IP => Integer ===
 +
 +  # vi ip2int.sh
 +
 +  #!/bin/bash
 +  
 +  echo "${1}" | awk -F'.' '{print $1"\n"$2"\n"$3"\n"$4}' | nl | while read N Z
 +  do
 +          echo "${N} ${Z}" | awk '{lfdn=$1 ; if (lfdn == 1) f='256*256*256' ; if (lfdn == 2) f='256*256' ; if (lfdn == 3) f=256 ; if (lfdn == 4) f=1 ; print f*$2}'
 +  done | awk '{z=$1;s+=z}END{print s}'
 +
 +  # /bin/bash ip2int.sh 192.168.1.100
 +  3232235876
 +  
 +  # /bin/bash ip2int.sh 255.255.255.0
 +  4294967040
 +
 +
 +=== Integer => Binär ===
 +
 +  # echo "$1" | awk '{for (i=0; $1>=2^i; i++); i--; Z=2^i} END {print i,Z}'
 +  
 +  exit
 +  
 +  # solange die erste Zahl >=0 ist, weitermachen:
 +  
 +  # /var/tmp/test2.sh 4294967040
 +  31 2147483648
 +  
 +  # echo "4294967040-2147483648"|bc -l
 +  2147483392
 +  
 +  # /var/tmp/test2.sh 2147483392
 +  30 1073741824
 +
 +Das mach ich später fertig, hab jetzt keine Zeit mehr...  FIXME
 +
 +
 +==== Zahlen formatiert ausgeben ====
 +
 +  c       Ein ASCII-Zeichen.
 +          Ist das entsprechende Argument eine Zahl,
 +          so wird diese als Kode im Zeichensatz interpretiert und ausgegeben.
 +  d       Eine vorzeichenbehaftete Integerzahl
 +  i       Eine vorzeichenbehaftete ganze Zahl.
 +  e       Eine Gleitkommazahl der Form: [-]d.ddddddE[+-]dd
 +  f       Eine Gleitkommazahl der Form: [-]ddd.dddddd
 +  g       das Argument wird entweder wie e oder f umgewandelt.
 +          Je nachdem, welches Ergebnis kürzer ist.
 +          Nicht signifikante Nullen werden dabei unterdrückt.
 +  o       Eine vorzeichenlose Oktalzahl.
 +  s       Ein String.
 +  u       Eine vorzeichenlose ganze Zahl.
 +  x       Eine vorzeichenlose Hexadezimalzahl mit Kleinbuchstaben. 
 +  X       Eine vorzeichenlose Hexadezimalzahl mit Großbuchstaben.
 +  %       Hebt die bedeutung von % auf. Also %% gibt % aus.
 +  abs(x)  Funktion zum ausgeben vom Absolutwert von x
 +  int(x)  Ganzzahliger Anteil von x
 +  log(x)  natürlicher Logarithmus von x
 +  rand()  Eine Zufallszahl z: 0 <= z < 0
 +  sqrt(x) Wurzel aus x
 +  
 +  # echo "10 50" | awk 'func abs(x) {return ((x < 0.0) ? -x : x)} {printf "%.0f\n", abs($1 - $2)}'
 +  
 +  # echo "1021 576" | awk '{printf("%d %d\n",($1/($1/720))/2,($2/($1/768))/2)}'
 +  # echo "1021 576" | awk '{printf("%i %i\n",($1/($1/720))/2,($2/($1/768))/2)}'
 +  # echo "1021 576" | awk '{printf("%u %u\n",($1/($1/720))/2,($2/($1/768))/2)}'
 +  # echo "1021 576" | awk '{printf("%uk\n",$1*$2*1000/69120)}'
 +
 +**__Rechengenauigkeit__**
 +  # echo "76.1 81.8 3.1415926535897932384626433832795028841971693993751" | awk '{print ($2/2)^2*$3*$1/1000}'
 +  399.927
 +  
 +  # echo "76.1 81.8 3.1415926535897932384626433832795028841971693993751" | awk '{OFMT="%.16G";print ($2/2)^2*$3*$1/1000}'
 +  399.9273868814023
 +  
 +  # echo "76.1 81.8 3.1415926535897932384626433832795028841971693993751" | awk '{OFMT="%.13f";print ($2/2)^2*$3*$1/1000}'
 +  373,9770000000000
 +  
 +  # echo "76.1 81.8 3.1415926535897932384626433832795028841971693993751" | awk '{OFMT="%.14f";print ($2/2)^2*$3*$1/1000}'
 +  373,97699999999998
 +  
 +  # echo "76.1 81.8 3.1415926535897932384626433832795028841971693993751" | awk '{OFMT="%.23G";print ($2/2)^2*$3*$1/1000}'
 +  399.92738688140229896817
 +  
 +  # echo "(81.8/2)^2 * 3.1415926535897932384626433832795028841971693993751 * 76.1 / 1000" | bc -l
 +  399.92738688140234827240
 +
 +----
 +Aus einer Datei soll die letzte Spalte von allen Zeilen ausgegeben werden,
 +die "78378" aber nicht "sftp" enthalten:
 +
 +  # export SUCHPATTERN="78378"
 +  # awk '/'$SUCHPATTERN'/ && !/sftp/ {printf("%s ", $NF);}' [Datei]
 +  
 +  # awk '/78378/ && !/sftp/ {printf("%s ", $NF);}' [Datei]
 +
 +Es entspricht dem Aufruf:
 +  # cat [Datei] | grep '78378' | grep -v 'sftp' | awk '{printf("%s ", $NF);}'
 +
 +Die letzte Spalte an den Anfang setzen, egal wieviel Spalten die Zeile hat:
 +  # awk '{ printf $NF;$NF = "" ;printf " "$0"\n" }'
 +
 +Wenn die Spalte 4 groesser ist als Spalte 6
 +oder wenn in Spalte 7 eine Zahl steht, die groesser als 30000 ist,
 +wird die Zeile ausgegeben:
 +  # awk '$4 < $6 || $7 > 30000'
 +
 +Es wird die Zeile ausgegeben, in der von Spalte 7, die Groesste Zahl steht:
 +  # vi script.awk
 +        max < $7 { max = $7 ; stadt = $1 }
 +        END { print "Die meisten Zuschauer waren in",stadt,"("max")." }
 +
 +  # awk -v max=0 -f script.awk
 +
 +mit AWK alles in Großbuschtaben umwandeln:
 +  # echo "buchstaben" | awk '{print toupper($0)}'
 +  BUCHSTABEN
 +
 +mit AWK alles in Kleinbuschtaben umwandeln:
 +  # echo "BUCHSTABEN" | awk '{print tolower($0)}'
 +  buchstaben
 +
 +AWK als grep:
 +  # awk '/PATERN/'                  # alle Zeilen mit "PATTERN"
 +  # awk '/^[0-9]+/ {print $1}'      # das erste Wort aller Zeilen mit einer Ziffer am Anfang
 +  # awk '/^[0-9]+|^#/'              # alle Zeilen mit einer Ziffer oder "#" am Anfang
 +  # awk '/[^n]{print $1}'           # es werden nur Zeilen verarbeitet, in denen kein "n" vorkommt
 +  # awk 'lenght() > 50 {print}'     # nur Zeilen die laenger als 50 Zeichen sind
 +
 +AWK als sed:
 +  # awk '/Anfang/,/Ende/'           # Textabschnitte von "Anfang" bis "Ende"
 +  # awk -v neu="-" '{$2 = neu;print};'              # zweite Spalte wird durch "-" ersetzt
 +  # awk -v alt='_' -v neu='-' '{sub(alt, neu); print}'              # einfache Ersetzung
 +  # awk -v alt='_' -v neu='-' '{gsub(alt, neu); print}'             # globale Ersetzung
 +  # awk '{alt="_"; neu="-"} {gsub(alt, neu); print}'                # globale Ersetzung
 +
 +Beispiel:
 +  * rein: D00D2 00010 31/12/2008 102
 +  * raus: D00D2 00010 20081231 102
 +
 +  # awk '{ alt="/"; neu=" "; gsub(alt, neu); $1; $2; $5$4$3; $6 print }'
 +
 +Es sollen nur die Leerzeichen der Variablen (vor dem Gleichheitszeichen) gegen Unterstriche ausgetauscht werden, nicht jedoch die Leerzeichen der Werte (hinter dem Gleichheitszeichen). Dazu wird vor der Veränderung der Wert in eine Variable gespeichert:
 +
 +  # echo "CPU Signature=Type 0, Family 6, Model 26, Stepping 5" | awk -F'=' '{wert=$2 ; gsub(" ", "_") ; print $1"="wert}'
 +  CPU_Signature=Type 0, Family 6, Model 26, Stepping 5
 +
 +Und jetzt noch zusätzlich die Variablen von Großschreibung in Kleinschreibung umwandeln.
 +
 +  # echo "CPU Signature=Type 0, Family 6, Model 26, Stepping 5" | awk -F'=' '{wert=$2 ; gsub(" ", "_") ; variable=tolower($1) ; print variable"="wert}'
 +  cpu_signature=Type 0, Family 6, Model 26, Stepping 5
 +
 +Zeilenlängen einer Datei ermitteln
 +  # wc -L [dateiname].csv
 +  # awk '{print length;exit}' [dateiname].csv
 +  78
 +
 +CSV (comma separated version) in "feste Spaltenbreite" umwandeln
 +
 +12 Zeichen breite Spalte generieren: "%12s"
 +  # awk -F';' '{printf("%12s%9s%13s%14s%9s\n", $1,$2,$5,$6,$7)}' daten.txt
 +       spalte1  spalte2      spalte5       spalte6  Spalte7
 +            13        1       092007    01/31/2099       al
 +            52        1       092009    08/31/2009       al
 +            62        1       092009    08/31/2009       al
 +            64        1       092009    08/31/2009       al
 +            71        1       092009    08/31/2009       al
 +            85        1       092009    08/31/2009       al
 +
 +# Da wo das Komma steht, werden die Freiräume mit Leerzeichen
 +# aufgefüllt.
 +
 +  # echo "Spalte01|Spalte02|Spalte03|Spalte4|Spalte5|Spalte6" | awk -F'|' '{printf ("%10s%16s%16s%16s%24s%21s\n", $1" | ",$2" | ",$3" | ",$4" | ",$5" | ",$6)}'
 +
 +
 +allerdings sind die Einträge in der ersten Spalte immer __rechtsbündig__:
 +  > echo "innodb_file_per_table ON" | awk '{printf("%47s%47s\n",$1" = ",$2)}'
 +                         innodb_file_per_table =                                              ON
 +
 +will man sie __linksbündig__, dann kann man das so machen:
 +  > echo "innodb_file_per_table ON" | rev | awk '{printf("%47s%47s\n",$1" = ",$2)}' | rev | sed 's/[ ]*$//'
 +  innodb_file_per_table                           = ON
 +
 +----
 +
 +Muss man einen String innerhalb eines Stringes (Unterstring => SubString) zerlegen, also zum Beispiel ein Datum in einem Satz umformen, dann bietet sich die Funktion //substr// in //AWK// an:
 +
 +  echo "Das Datum 21.03.1969 im klassischen Format." | awk '{print $1,$2,substr($3,7,4)"-"substr($3,4,2)"-"substr($3,1,2),$4,"Euro-"$6}'
 +  Das Datum 1969-03-21 im Euro-Format.
 +
 +//substr// benötigt drei Parameter:
 +
 +  - "Spalte" bzw. "Wort" aus dem Originalstring;
 +  - ab dem wievielten Zeichen von dieser "Spalte" bzw. "Wort" wieder gegeben werden soll;
 +  - wieviel Zeichen aus dieser "Spalte" bzw. "Wort" wieder gegeben werden sollen;
 +
 +die ersten beiden Zeichen einer Zeichenkette ausgeben:
 +  echo "${STRING}" | awk '{print substr($1,1,2)}'
 +
 +die letzten beiden Zeichen einer Zeichenkette ausgeben:
 +  echo "${STRING}" | awk '{a=length($1)-1; print substr($1,a,2)}'
 +----
 +
 +  * [[http://www.pement.org/awk/awk1line.txt]]
 +
 +Will man zum Beispiel die Werte "cpu family", "model" und "stepping" einer CPU unter Linux auslesen,
 +dann kann man einfach in dieser Datei nachsehen:
 +
 +  # cat /proc/cpuinfo
 +  
 +  processor       : 0
 +  vendor_id       : GenuineIntel
 +  cpu family      : 15
 +  model           : 2
 +  model name      : Intel(R) Pentium(R) 4 CPU 2.60GHz
 +  stepping        : 9
 +  cpu MHz         : 2593.547
 +  cache size      : 512 KB
 +  fdiv_bug        : no
 +  hlt_bug         : no
 +  f00f_bug        : no
 +  coma_bug        : no
 +  fpu             : yes
 +  fpu_exception   : yes
 +  cpuid level     : 2
 +  wp              : yes
 +  flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe up pebs bts cid xtpr
 +  bogomips        : 5187.09
 +  clflush size    : 64
 +  power management:
 +
 +Hat diese CPU allerdings mehr als einen Kern, dann wird es schnell unübersichtlich:
 +
 +  # cat /proc/cpuinfo
 +  
 +  processor     : 0
 +  vendor_id     : GenuineIntel
 +  cpu family    : 6
 +  model         : 26
 +  model name    : Intel(R) Xeon(R) CPU           X5570  @ 2.93GHz
 +  stepping      : 5
 +  cpu MHz               : 2926.105
 +  cache size    : 8192 KB
 +  physical id   : 1
 +  siblings      : 8
 +  core id               : 0
 +  cpu cores     : 4
 +  apicid                : 16
 +  initial apicid        : 16
 +  fpu           : yes
 +  fpu_exception : yes
 +  cpuid level   : 11
 +  wp            : yes
 +  flags         : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 lahf_lm ida tpr_shadow vnmi flexpriority ept vpid
 +  bogomips      : 5852.21
 +  clflush size  : 64
 +  cache_alignment       : 64
 +  address sizes : 40 bits physical, 48 bits virtual
 +  power management:
 +  
 +  ...
 +    
 +  processor     : 15
 +  vendor_id     : GenuineIntel
 +  cpu family    : 6
 +  model         : 26
 +  model name    : Intel(R) Xeon(R) CPU           X5570  @ 2.93GHz
 +  stepping      : 5
 +  cpu MHz               : 2926.105
 +  cache size    : 8192 KB
 +  physical id   : 0
 +  siblings      : 8
 +  core id               : 3
 +  cpu cores     : 4
 +  apicid                : 7
 +  initial apicid        : 7
 +  fpu           : yes
 +  fpu_exception : yes
 +  cpuid level   : 11
 +  wp            : yes
 +  flags         : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 lahf_lm ida tpr_shadow vnmi flexpriority ept vpid
 +  bogomips      : 5851.96
 +  clflush size  : 64
 +  cache_alignment       : 64
 +  address sizes : 40 bits physical, 48 bits virtual
 +  power management:
 +
 +Die oben gezeigte Ausgabe stammt von einem Dual-Quad-Core mit Hyper-Threading. Also sind es nur zwei CPUs mit je vier Kernen, die über erweiterte Register verfühgt, wodurch der einzelne Kern zwischen zwei Pipes schneller hin und her springen kann.
 +
 +Hyper-Threading bringt nur einen Geschwindigkeitsvorteil, wenn man mehr Prozesse laufen lassen möchte als sich CPU-Kerne im System befinden!
 +An sonsten werden z.B. die ersten beiden Prozesse auf die ersten beiden virtuellen CPUs gestartet, wobei das aber der selbe Kern (mit Hyper-Threading) ist und alle anderen CPU-Kerne haben nix zu tun.
 +
 +Deshalb sollte man HT (Hyper-Threading) im BIOS nur dann aktivieren, wenn man vilele Prozesse fährt.
 +
 +Möchte man
 +  - nur diese drei Parameter und
 +  - nur vom ersten CPU-Kern-Block (also nur ein einziges mal)
 +dann kann man sich alles, bis zu der Zeile anzeigen lassen, in der "stepping" das erste mal vorkommt:
 +
 +  sed -e '/stepping/ q' /proc/cpuinfo
 +  
 +  processor       : 0
 +  vendor_id       : GenuineIntel
 +  cpu family      : 6
 +  model           : 26
 +  model name      : Intel(R) Xeon(R) CPU           X5570  @ 2.93GHz
 +  stepping        : 5
 +
 +Das ist schon sehr viel übersichtlicher und enthält auch alle Informationen, die wir brauchen.
 +
 +Allerdings werden auch da noch viele unnütze Infos angezeigt, die rausgefiltert werden sollen.
 +
 +Filtert man jetzt nach der klassischen Art mit "grep", dann könnte das so aussehen:
 +
 +  # sed -e '/stepping/ q' /proc/cpuinfo | egrep 'cpu family|model|stepping' | fgrep -v 'model name' | awk '{print $NF}'
 +  
 +  6
 +  26
 +  5
 +
 +Das gleiche Ergebnis kann man allerdings auch bekommen, wenn man an Stelle von drei Prozessen (egrep, fgrep und awk)
 +nur einen aufruft (awk):
 +
 +  # sed -e '/stepping/ q' /proc/cpuinfo | awk '/cpu family|model|stepping/ && !/model name/ {print $NF}'
 +  
 +  6
 +  26
 +  5
 +
 +Denn //AWK// kann alles, was grep kann.
 +