Ten jednowarstwowy usuwa zduplikowane linie z wprowadzania tekstu bez wstępnego sortowania.
Na przykład:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
Oryginalny kod znaleziony w Internecie brzmiał:
awk '!_[$0]++'
Było to dla mnie jeszcze bardziej kłopotliwe, ponieważ wziąłem _
specjalne znaczenie w awk, podobnie jak w Perlu, ale okazało się, że to tylko nazwa tablicy.
Teraz rozumiem logikę stojącą za linią jednokreskową: każda linia wejściowa jest używana jako klucz w tablicy mieszającej, dlatego po zakończeniu skrót zawiera unikalne wiersze w kolejności nadejścia.
Chciałbym się dowiedzieć, jak dokładnie interpretacja tego zapisu jest interpretowana przez awk. Np. Co oznacza znak huku ( !
) i inne elementy tego fragmentu kodu.
Jak to działa?
Odpowiedzi:
Zobaczmy,
pierwszy
patrzymy na wartość
a[$0]
(tablicaa
z całą linią wejściową ($0
) jako kluczem).Jeśli nie istnieje (
!
czy negacja w teście stanie się prawdą)wypisujemy wiersz wejściowy
$0
(akcja domyślna).Dodajemy również jeden (
++
)a[$0]
, więc następnym razem!a[$0]
zostanie ustawiona wartość false.Fajnie, znajdź !! Powinieneś rzucić okiem na kod golfa!
źródło
awk
jako test dla każdej linii wejściowej; za każdym razem, gdy test się powiedzie,awk
wykonuje akcję w nawiasach klamrowych, co w przypadku pominięcia jest{print}
. Dzięki!awk
, akcja domyślna to{print $0}
. Oznacza to, że wszystko ocenione jako prawda, wykona to jako domyślną. Na przykładawk '1' file
drukuje wszystkie linie,awk '$1' file
drukuje wszystkie linie, których pierwsze pole nie jest puste lub 0, itd.Oto przetwarzanie:
a[$0]
: spójrz na wartość klucza$0
w tablicy asocjacyjneja
. Jeśli nie istnieje, utwórz go.a[$0]++
: zwiększ wartośća[$0]
, zwróć starą wartość jako wartość wyrażenia. Jeżelia[$0]
nie istnieje, powrót0
i przyrosta[$0]
do1
(++
wraca operatora wartości numeryczne).!a[$0]++
: zaneguj wartość wyrażenia. Jeślia[$0]++
return0
, całe wyrażenie jest oceniane na true, należy wykonaćawk
domyślną akcjęprint $0
. W przeciwnym razie całe wyrażenie zostanie ocenione na false,awk
ponieważ nic nie robi.Referencje:
Za pomocą
gawk
możemy użyć dgawk (lubawk --debug
nowszej wersji) do debugowaniagawk
skryptu. Najpierw utwórzgawk
skrypt o nazwietest.awk
:Następnie uruchomić:
lub:
W konsoli debuggera:
Widać,
Op_postincrement
został stracony wcześniejOp_not
.Możesz także użyć
si
lubstepi
zamiasts
lub,step
aby lepiej widzieć:źródło
!
została zastosowana wcześniej++
.!
obliczeniu wyniku operatora. Mylisz pierwszeństwo operatora (!a[$0]++
jest parsowane jak!(a[$0]++)
) z kolejnością oceny (przypisanie nowej wartościa[$0]
zdarza się po obliczeniu wartości wyrażenia).!x
obliczana jest wartość , gdziex
jest stara wartośća[$0]
. Następniea[$0]
jest ustawiony na1+x
.