Моя первая идея заключалась в следующем:
printf "%s\n" *.txt | xargs -n1 sed -i "$(sed 's!.*!/& /d!' to_delete.txt)"
printf "%s\n" *.txt
- выводит файлы * .txt каждый в отдельных строках | xargs -n1
выполняет следующую команду для каждогострока, передающая содержимое строки в качестве ввода sed -i
- отредактировать файл на месте $( ... )
- подстановка команды sed 's!.*!/^& /d!' to_delete.txt
- для каждой строки в to_delete. txt, добавьте строку с /^
и суффикс с /d
. Таким образом, из списка чисел я получаю список регулярных выражений для удаления, например:
/^2 /d
/^3 /d
/^6 /d
и так далее. Что говорит sed
об удалении строк, соответствующих регулярному выражению - строка начинается с числа, за которым следует пробел.
Но я думаю, что awk
будет проще. Вы можете сделать:
awk '$1 != 2 && $1 != 3 && $1 != 6 ... and so on ...`
, но это будет длинным, нечитаемым. Проще прочитать карту из файла, а затем проверить, находится ли число в массиве:
awk 'FNR==NR{ map[$1] } FNR!=NR && !($1 in map)' to_delete.txt "$file"
Значение FNR==NR
верно только для первого файла. Поэтому, когда мы читаем его, мы устанавливаем map[$1]
(мы его «устанавливаем», именно так такой элемент существует). Тогда FNR!=NR
верно для второго файла, для которого мы проверяем, является ли первый элемент ключом на карте. Если это не так, выражение является истинным, и строка выводится на печать.
все вместе:
for file in *.txt; do awk 'FNR==NR{ map[$1] } FNR!=NR && !($1 in map)' to_delete.txt "$file" > "$tmp"; mv "$tmp" "$file"; done