Эта однострочная строка удаляет повторяющиеся строки из текстового ввода без предварительной сортировки.
Например:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
Оригинальный код, который я нашел в интернете, читал:
awk '!_[$0]++'
Это было еще более озадачивающим для меня, так как я принял _
особое значение в awk, как в Perl, но оказалось, что это просто имя массива.
Теперь я понимаю логику, стоящую за однострочником: каждая строка ввода используется в качестве ключа в хэш-массиве, таким образом, после завершения хеш-код содержит уникальные строки в порядке поступления.
Я хотел бы узнать, как именно это обозначение интерпретируется awk. Например, что !
означает знак взрыва ( ) и другие элементы этого фрагмента кода.
Как это работает?
Ответы:
Посмотрим,
первый
мы смотрим на значение
a[$0]
(массивa
с целой строкой ввода ($0
) в качестве ключа).Если он не существует (
!
отрицание в тесте будет равно true)мы печатаем строку ввода
$0
(действие по умолчанию).Кроме того, мы добавляем one (
++
) кa[$0]
, так что в следующий раз мы!a[$0]
получим значение false.Здорово, найди !! Вы должны взглянуть на код гольф!
источник
awk
в качестве теста для каждой входной строки; каждый раз, когда тест завершается успешно,awk
выполняется действие в фигурных скобках, которое, если оно опущено, равно{print}
. Благодарность!awk
, действие по умолчанию -{print $0}
. Это означает, что все, что оценено как истинное, выполнит это по умолчанию. Так, например,awk '1' file
печатает все строки,awk '$1' file
печатает все те строки, чье первое поле не пустое или 0 и т. Д.Вот обработка:
a[$0]
: посмотрите на значение ключа$0
в ассоциативном массивеa
. Если его не существует, создайте его.a[$0]++
: увеличить значениеa[$0]
, вернуть старое значение в качестве значения выражения. Еслиa[$0]
не существует, вернуть0
и увеличитьa[$0]
до1
(++
оператор возвращает числовое значение).!a[$0]++
: отрицание значения выражения. Еслиa[$0]++
возвращено0
, все выражение оценивается как true, выполнитьawk
выполненное действие по умолчаниюprint $0
. В противном случае все выражение оценивается как ложное, причиныawk
ничего не делают.Ссылки:
С помощью
gawk
мы можем использовать dgawk (илиawk --debug
с более новой версией) для отладкиgawk
скрипта. Сначала создайтеgawk
скрипт с именемtest.awk
:Затем запустите:
или:
В консоли отладчика:
Как видите,
Op_postincrement
был казнен раньшеOp_not
.Вы также можете использовать
si
илиstepi
вместоs
илиstep
чтобы видеть более четко:источник
!
применяется раньше++
.!
вычисления результата оператора. Вы путаете приоритет оператора (!a[$0]++
аналогично синтаксическому анализу!(a[$0]++)
) с порядком вычисления (присвоение нового значенияa[$0]
происходит после вычисления значения выражения).!x
вычисляется значение , гдеx
находится старое значениеa[$0]
. Затемa[$0]
устанавливается на1+x
.