AWK

Aus WS64 Wiki
Wechseln zu: Navigation, Suche

awk_deutsch.pdf

Cheat Sheet 1 (PDF)

Cheat Sheet 2 (DOCX)

Invoking Awk: 
   awk [-F<ch>] {pgm} | {-f <pgm file>} [<vars>] [-|<data file>]
-- where: 
   ch:          Field-separator character.
   pgm:         Awk command-line program.
   pgm file:    File containing an Awk program.
   vars:        Awk variable initializations.
   data file:   Input data file.
AWK Library

# PATH Variables, each in a new line, headline separated:
path | awk "{str=$0;gsub(\";\",\"\n\",str);sub(\"=\",\"\n\n\",str);print str}"
# gsub: alle Vorkommen von ; durch Zeilenumbruch. sub: erstes Vorkommen von = durch 2 Zeilenumbrüche ersetzen

# Leerzeilen weg
awk "NF>0" 1.txt

# doppelte aufeinanderfolgende Zeilen raus
awk "{if (a!=$0) {print $0};a=$0}" 1.TXT

# Anzahl Zeilen
awk "END { print NR \" lines\" }" 1.TXT

# Anzahl Wörter
awk "{ nw += NF } END { print nw \" words\"}" 1.TXT

# Anzahl Buchstaben
awk "{ nc += length($0) } END { print nc \" chars\" }" 1.TXT

# Anzahlen
awk "{ nw += NF;nc += length($0);if (NF==0) e++;} END { print \"\nFile : \" FILENAME \"\nLines: \" NR \" (empty: \" e+0 \")\nWords: \" nw \"\nChars: \" nc}" 1.TXT

# Erzeuge Copy-Befehl, der den Dateinamen durch den Verzeichnispfad ersetzt
dir /b /s *.bat | awk -v wobinich=%cd:\=/% -F\ "BEGIN {print \"REM Copy Filename to last Directoryname\";a=\"\x22\";bs=\"\x5c\";b=\" \";split(wobinich,ar,\"/\");start=length(ar)}{split($NF,ex,\".\");t=$(start);s=$(start);for (i=start+1;i<NF;i++){t=t bs $i;s=s \"_\" $i};print \"copy \"a $0 a b a t bs s  \".\" ex[length(ex)] a}"

# Hänge allen Files in CSV noch ein Semikolon plus Dateinamen (ohne Extension) an
awk.exe -F; "$1!~/CWID/ {print $0\";\"substr(substr(FILENAME,1,length(FILENAME)-4),5)}" csv\*.csv > All.csv
# der innere substr entfernt die Extension, der äussere das 3stellige Verzeichnis (CSV) vorne

#Nummeriere Textfile, aber nicht die Leerzeilen
NF {c=++a;printf ("%5d: %s\n",c,$0)} NF==0

#Sortieren und doppelte Zeilen raus (Leerzeilen auch)
NF {a[$0]=1} END {for (i=1;i<asorti(a,b);i++)print b[i];printf b[i]}
#ungeordnet (durcheinander!) plus Leerzeile, aber schneller (7MB/12000DS: ~3 min sortiert, <1 sek unsortiert):
NF {a[$0]=1} END {for (w in a) print w}

#nur Zeilen die suchtext enthalten
awk "/suchtext/"
#insert before or after other files
BAT:
@echo off
cls

set search="export LC_ALL=\"en_US.UTF-8\""
set insertbefore=
set insertafter="mount -r /dev/mmcblk0p5 /mnt/ws"
copy koreader.sh koreader.sh_backup
awk -v search=%search% -v insertbefore=%insertbefore% -v insertafter=%insertafter% -f patch.awk koreader.sh_backup > koreader.sh
dos2unix -U koreader.sh

set search="    self.pageturn_count = self.pageturn_count + 1"
set insertbefore="os.execute(\"hwclock -s -u\")"
set insertafter=
copy plugins\statistics.koplugin\main.lua plugins\statistics.koplugin\main.lua_backup
awk -v search=%search% -v insertbefore=%insertbefore% -v insertafter=%insertafter% -f patch.awk plugins\statistics.koplugin\main.lua_backup > plugins\statistics.koplugin\main.lua
dos2unix -U plugins\statistics.koplugin\main.lua

AWK:
BEGIN {
	i=0
	foundafter=0
}
{
	n++
	a[n]=$0
	if (foundafter==1){
		if (a[n]!=insertafter) {
			a[n]=insertafter
			n++
			a[n]=$0
		}
	}
	if (a[n]==search) {
		if (insertafter>"" && foundafter==0) {
			foundafter=1
		}
		else foundafter=0
		if (insertbefore>"") {
			if (a[n-1]!=insertbefore) {
				a[n+1]=a[n]
				a[n]=insertbefore
				n++
			}
		}
	}
	else foundafter=0
}
END {
	for (i=1;i<=n;i++)
		print a[i]
} 
@echo off

echo @echo off > backslash2slash.bat
echo awk "{a=$0;sub(/\\/,\"/\",a);print a}" %%1 ^> %%2 >> backslash2slash.bat

echo @echo off > make_Apple_m3us_copy.bat

dir /b /s _all.m3u | awk -v wobinich=%cd:\=/% -F\ "BEGIN {print \"REM Copy Filename to last Directoryname\";a=\"\x22\";bs=\"\x5c\";b=\" \";sl=\"\x2f\";nl=\"\x3e\" \"\x6e\" \"\x75\" \"\x6c\";split(wobinich,ar,\"/\");start=length(ar)+1}{split($NF,ex,\".\");t=$(start);s=$(start);for (i=start+1;i<NF;i++){t=t bs $i;s=s \"_\" $i};quelle=a $0 a;ziel=a t bs s  \".\" ex[length(ex)] a;gsub(/&/,\"and\",t);print \"echo \"t;print \"call backslash2slash.bat \" quelle b ziel}">> make_Apple_m3us_copy.bat

call make_Apple_m3us_copy.bat

del make_Apple_m3us_copy.bat
del backslash2slash.bat

Trim Funktion:

function ltrim(s) { sub(/^[ \t\r\n]+/, "", s); return s }
function rtrim(s) { sub(/[ \t\r\n]+$/, "", s); return s }
function trim(s) { return rtrim(ltrim(s)); }
BEGIN {
# whatever
}
{
# whatever
}
END {
# whatever
} 

CSV:

{
	n=split($0,a,von)
	for (i=1;i<=n;i++) {
		if (substr(a[i],1,1)=="\x22" && substr(a[i],length(a[i]))!="\x22") {
			a[i]=a[i] von a[i+1]
			for (j=i+1;j<n;j++) a[j]=a[j+1]
			a[n]=""
			n=n-1
			i=i-1
		}
	}

	s=""
	for (i=1;i<=n;i++) {
		if (substr(a[i],1,1)=="\x22") a[i]=substr(a[i],2,length(a[i])-2)
		s=s a[i] nach
	}
	print substr(s,1,length(s)-1)
}

Aufruf: awk -v von="," -v nach="|" -f csv.awk datei.csv Todo: Abfangen von Zeilenumbrüchen


Weiter Beispiele:

# das letzte Feld jeder Eingabezeile ausgeben
  awk '{ print $NF }' /etc/hosts
  
  # die 10. Eingabezeile ausgeben
  awk 'NR == 10' /etc/passwd
  
  # alle Zeilen ausgeben, die entweder "root" oder "false" enthalten
  # (also Suche wie bei egrep)
  awk '/root|false/' /etc/passwd
  
  # Gesamtzahl der Eingabe-Zeilen ausgeben
  awk 'END { print NR }' /etc/passwd
  
  # das erste und letzte Feld der Eingabezeilen 5 bis 10 ausgeben
  awk -F: 'NR == 5, NR == 10 { print $1, $NF }' /etc/passwd
  
  # das erste und vorletzte Feld der letzten Eingabezeile ausgeben
  awk -F: 'END { print $1, $(NF-1) }' /etc/passwd
  
  # passwd-Eintrag für die aktuelle UID ausgeben
  awk -F: "\$3 == $UID" /etc/passwd
  awk -F: -v uid=$UID '$3 == uid' /etc/passwd
  
  # Ausgabe von Zeilen mit mehr als 2 Feldern
  awk 'NF > 2' /etc/hosts
  
  # Ausgabe von Zeilen, deren Feld 3 kleiner als 50 ist
  awk -F: '$3 < 50' /etc/passwd
  
  # Ausgabe von Zeilen, deren letztes Feld "false" enthält
  awk -F: '$NF ~ /false/' /etc/passwd
  
  # Ausgabe der Anzahl von Zeilen, deren letztes Feld "false" enthält;
  # Anmerkung: das Semikolon vor END ist nicht nötig
  awk -F: '$NF ~ /false/ { anz++ } ; END { print anz }' /etc/passwd
  
  # Ausgabe von nicht leeren Zeilen;
  # NF wird hier im Booleschen Kontext ausgewertet (0 ist FALSE, der Rest TRUE)
  awk NF /etc/hosts
  
  # ermittle, wie oft jeder Wert des letzten Feldes der Eingabezeilen vorkommt
  awk -F: '
    { ANZ[$NF]++ }
    END { for (w in ANZ) printf("%s: %d\n", w, ANZ[w]) }
  ' /etc/passwd
  
  # tausche Feld 1 und 2 der ersten 10 Eingabezeilen; gib die restlichen Zeilen
  # unverändert aus; für die Ausgabe nutzen wir eine Regel, die nur aus dem
  # Muster 1 (also TRUE) besteht und deren Aktion dann print lautet
  awk -F: '
    BEGIN { OFS = FS }
    NR < 11 { t = $1; $1 = $2; $2 = t }
    1
  ' /etc/passwd
  
  # ermittle die längste Eingabe-Zeile
  awk '
    length($0) > max { max = length($0) ; fn = FILENAME ; fnr = FNR ; line = $0 }
    END { if (fnr) printf("%d Zeichen in Zeile %d in Datei %s\n%s\n", max, fnr, fn, line) }
  ' /etc/{hosts,passwd}
  
  # gib die UIDs der Nutzer, die die bash als Login-Shell haben, fallend sortiert
  # aus; anschließend wird noch die Anzahl dieser Nutzer ausgegeben
  awk -F: '
    BEGIN { sort = "sort -rn" }
    $7 ~ /bash/ { print $3 | sort ; anz++ }
    END { close(sort) ; printf("Anzahl: %d\n", anz) }
  ' /etc/passwd
  
  # Einrücken der Inhalte von HTML-Absätzen;
  # Annahme: <p> und </p> stehen jeweils auf getrennten Zeilen und sollen selbst
  # nicht mit eingerückt werden
  awk '/<p>/, /<\/p>/ {if ($0 !~ /<\/?p>/) {print "  " $0; next}}; 1' p.html
  
  # alternativ funktioniert das auch ohne "next", indem die erste Regel, deren
  # Muster einen Bereich spezifiziert, nur 2 Leerzeichen als Präfix der
  # Einrückung ausgibt, wogegen der Zeileninhalt dann von der zweiten Regel
  # ausgegeben wird, die auch der Ausgabe der nicht eingerückten Zeilen außerhalb
  # der Bereiche dient
  awk '/<p>/, /<\/p>/ {if ($0 !~ /<\/?p>/) {printf("  ")}}; 1' p.html
  
  # die Auswahl von Bereichen kann auch durch eigene Statusvariablen erfolgen
  awk '
    /<p>/   { in_p = 1; print; next }
    /<\/p>/ { in_p = 0; print; next }
    in_p    { print "  " $0; next}
    1
  ' p.html
  
  # obige Regeln kann man kürzer formulieren, wenn man sie geeignet anordnet, so
  # dass je nach Datenkonstellation die richtige Aktion erfolgt
  awk '
    /<\/p>/ { in_p = 0 }
    in_p    { printf("  ") }
    /<p>/   { in_p = 1 }
    1
  ' p.html
Meine Werkzeuge
Kategorien
Arbeit
Misc
Music
Privat
PUBLIC