Tato jednořádková linka odstraňuje duplicitní řádky ze vstupu textu bez předběžného třídění.
Například:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
Původní kód, který jsem našel na internetu, zněl:
awk '!_[$0]++'
Když jsem vzal _
, bylo to pro mě ještě více matoucí mít speciální význam v awk, jako v Perlu, ale ukázalo se, že je to jen název pole.
Nyní rozumím logice za jednořádkovou linkou:
každý vstupní řádek se používá jako klíč v poli hash, takže po dokončení obsahuje hash jedinečné řádky v pořadí, v jakém přicházejí.
Chtěl bych se naučit, jak přesně tento zápis interpretuje awk. Např. jaký je znak třesku (!
) znamená a další prvky tohoto fragmentu kódu.
Jak to funguje?
Přijatá odpověď:
Zde je „intuitivní“ odpověď, pro podrobnější vysvětlení mechanismu awk viz buď @Cuonglm
V tomto případě !a[$0]++
, přírůstek ++
lze na chvíli odložit, nemění to hodnotu výrazu. Podívejte se tedy pouze na !a[$0]
. Zde:
a[$0]
používá aktuální řádek $0
jako klíč k poli a
, přičemž hodnota tam uložená. Pokud tento konkrétní klíč nebyl nikdy předtím odkazován, a[$0]
vyhodnotí jako prázdný řetězec.
!a[$0]
!
neguje hodnotu z dřívějška. Pokud byl prázdný nebo nulový (nepravda), máme nyní výsledek true. Pokud by bylo nenulové (pravda), máme falešný výsledek. Pokud je celý výraz vyhodnocen jako true, což znamená, že a[$0]
nebyla nastavena na začátek, vytiskne se celý řádek jako výchozí akce.
Také, bez ohledu na starou hodnotu, operátor po přírůstku přidá jedničku do a[$0]
, takže při příštím přístupu ke stejné hodnotě v poli bude kladná a celá podmínka selže.