Всем привет. Вчера решал задачу фильтрации txt-файла и нашёл конструкцию на awk, от которой испытал эстетический оргазм. Решил с вами ею поделиться.
Итак, задача: есть _data.txt_ с данными и _filter.txt_ со списком фильтрации.
Строки data.txt обрабатываются, если есть совпадение в filter.txt. Это классическая задача фильтрации (например, обработка белых и чёрных списков).
ㅤИ да, я знаю про программы
comm и
join, с помощью которых можно решать подобные вещи, но мне нравится
awk, потому что делает это гибче благодаря наличию языка программирования и не требует предсортировки.
👍 Итак, сама конструкция:
awk 'NR == FNR { filter[$0] = 1; next } $0 in filter { print $0, "in filter" }' filter.txt data.txt
Обратите внимание: здесь два блока обработки строк, каждый со своим условием
1. NR == FNR { filter[$0] = 1; next }
2. $0 in filter { print $0, "in filter" }
Обычно выполняются оба блока: сначала первый, потом второй, но здесь это не так. Первый блок только считывает данные filter.txt в массив filter.
Второй обрабатывает только те строки, которые есть в массиве.
NR — встроенная переменная, номер записи ДЛЯ ВСЕХ файлов.
FNR — аналогична предыдущей, но начинается с 1 для каждого нового файла.
filter[$0] = 1 — сохраняем всю строку первого файла как ключ массива.
next — сразу переходит к обработке следующей строки.
Таким образом, связка условия NR == FNR и next будет работать только для первого файла (filter.txt).
Для второго файла условие NR == FNR уже не соблюдается, поэтому первый блок не выполняется, а второй выполняется, если строка данных присутствует в массиве filter.
Ну и пример из реальной жизни — filter.txt:
RU
BY
data.txt
RU 127.0.0.1
BY 127.0.0.2
US 127.0.0.3
KZ 127.0.0.4
awk 'NR == FNR { filter[$1] = 1; next } $1 in filter { print $2, "in filter" }' filter.txt data.txt
127.0.0.1 in filter
127.0.0.2 in filter
Обратите внимание: на выходе только нужные строки и только нужный столбец. Как же это круто!
Маленькое ограничение: содержимое filter.txt, загруженное в массив filter, должно помещаться в оперативную память. Иначе система может начать активно использовать swap, а процесс — завершиться из-за нехватки памяти.
man awk
man comm
man join Всем работы без багов.
© Tagd Tagd
🛠
#devops #bash #linux—
💬 Bashdays 📲
MAX 🌐 LF 🔵 Blog