Удалять строки из одного файла, если они содержат регулярное выражение содержимого в другом файле

У меня большой файл (150K + строк), содержащий записи DNS, я буду называть это FileA. У меня есть файл меньшего размера, содержащий определенные имена, FileB. Я хочу удалить все строки в FileA, которые заканчиваются тем, что находится в FileB. Но я не хочу удалять строку, если имя появляется в начале записи.

Я знаю, как использовать grep -v name$ чтобы вручную удалить имена, которые появляются в конце записи, но мне нужен цикл, чтобы пройти через весь FileB. Пока мои попытки потерпели неудачу.

Вот пример, на который я надеюсь проиллюстрировать, что мне нужно:

 FileA: hosta IN A 10.20.30.40 hostb IN A 20.30.40.50 myurl IN CNAME hostb yours IN CNAME hostb 

Если FileB содержит hostb, удаляются только две последние строки; первые две строки остаются как есть.

3 Solutions collect form web for “Удалять строки из одного файла, если они содержат регулярное выражение содержимого в другом файле”

Вы можете использовать флаг -f для grep для всех строк в FileB:

 grep -v -f FileB FileA 

Это почти то, что вы хотите. Но это также удаляет строки, в которых шаблоны из FileB не заканчиваются, и вы явно заявили, что они должны соответствовать только тогда, когда они находятся в конце. Поэтому нам нужно соответствующим образом изменить FileB . Мы можем использовать sed , чтобы добавить regex для конца строки, которое является знаком $ :

 sed 's/$/$/' FileB 

Похоже, что это ничего не заменяет, но на самом деле добавляет $ на каждом конце строки.

Теперь мы можем использовать замену процессов, чтобы собрать все это вместе:

 grep -v -f <(sed 's/$/$/' FileB) FileA 

Чтобы перебрать весь FileB, вы можете использовать такой подход, как:

 for i in `cat FileB` do <do your work> done 

Но, возможно, будет лучше фильтровать также CNAME

С sed вы можете сделать это следующим образом:

 sed -n '/^[^ ]*$/{H;d;};G;/ \(.*\)\n.*\n\1/d;P' fileB fileA 

Это: Первый файл процесса. Если строки не содержат пробелов, они должны быть именами хостов в файлеB, и мы добавляем их в пространство удержания и продолжаем ( {H;d;} )

Все остальные строки должны быть fileA. Добавив пространство удержания в список имен узлов ( G ), все строки с последним словом строки, которые повторяются в списке имен узлов, могут быть удалены. Остальные строки печатаются без конечного списка ( P ). Опция -n отменяет вывод по умолчанию.

Изменить: на самом деле нужно делать

 sed -n '/^[^ ]*$/{H;d;};G;/ \(.*\)\n.*\n\1\n/d;/ \(.*\)\n.*\n\1$/d;P' fileB fileA 

чтобы избежать особых случаев.

  • Автоматическое ведение журнала скриптов, выполняемых пользователями
  • Скажите, как эта команда проверяет, имеет ли rnum целое число или нет
  • печатать дубликаты строк только в полях 1,2 из файла csv
  • Вывод команды при передаче по другой команде
  • Подавлять предупреждения от MySQL в сценарии оболочки, но допускать ошибки
  • Объединение аргументов bash в одну строку с пробелами
  • Объединение частичных дубликатов
  • Экстра% в выходе скрипта awk
  • seq - неверная ошибка аргумента с плавающей запятой
  • Спросить имя хоста в сценарии оболочки?
  • Как найти строки, содержащие более 100 символов, и содержит «if»?
  • Linux и Unix - лучшая ОС в мире.