Вопрос по unix – Объясните удаление этой повторяющейся строки, сохранение порядка, однострочный AWK

14

Я узнал очень удобный способ удалить повторяющиеся строки, сохраняя порядок изУдалить дубликаты без сортировки файлов - BASH.

Скажем, если у вас есть следующий файл,

$cat file
a
a
b
b
a
c

Вы можете использовать следующее, чтобы удалить дубликаты строк:

$awk '!x[$1]++' file
a
b
c

Как это работает с точки зрения приоритета операций?

@brandizzi извините за задержку! Я обычно жду 3 ~ 5 дней, чтобы выбрать лучший ответ Alby
@Oliver: приоритет оператора. Dennis Williamson
Я не понимаю вопроса? Удаляет дубликаты строк. Какой приоритет вы имеете в виду? Oliver
Просто примечание: он удалит не только дублированные строки, но иall lines with the same value at the first column, тоже! Добавить строку сd a а такжеd b в файл, и вы поймете, что я имею в виду. Чтобы удалить только дублированные строки, вы можете написать!x[$0]++, поскольку$0 возвращает всю строку, а не только первый столбец. Чтобы лучше это понять, смотрите ответ @larsmans. brandizzi

Ваш Ответ

2   ответа
22

Выражение разбирается как

!(x[$(1)]++)

Итак, изнутри, это:

Take field 1 of the current input line, $(1) (note that $ is an operator in AWK, unlike in Perl). Index x with the value of field 1; if x is an unbound variable, bind it to a new associative array. Post-increment x[$(1)]; a rule similar to the one in C applies, so the value of the expression is that of x[$(1)] prior to the increment, which will be zero if x[$(1)] has not yet been assigned a value. Negate the value of the previous, which will yield truth when x[$(1)] is zero. Actually do the increment so that x[$(1)] gets a non-zero value. So, the next time, x[$(1)] for the same value of $(1) will return 1.

Затем это выражение оценивается для каждой строки во входных данных и определяет, подразумевается ли подразумеваемое действие по умолчаниюawk должен быть выполнен, который должен повторить строкуstdout.

Просто дополнение:!x[$1]++ является выражением, которое, если true, выполнит следующий блок кода. Тем не менее, он не имеет никакого блока кода; в этом случае поведение по умолчанию заключается в выполненииprint команда, которая печатает текущую строку, если ей не задан параметр. Это означает, что в этом случае!x[$1]++ эквивалентно!x[$1]++{print;}, Итак, в первой строке возвращается значение$(1), результат!x[$1]++ будет истинным, и строка будет распечатана; в следующий раз, однако,!x[$1]++ выдаст false, и строки не будут напечатаны.
@brandizzi: хорошая мысль, добавил это.
0

поэтому первый столбец или первое поле каждой строки$1, используется в качестве индекса для массиваx.

Похожие вопросы