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

У меня большой файл (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, удаляются только две последние строки; первые две строки остаются как есть.

  • Как передать имя функции тестируемому?
  • Определить набор значений для переменной в сценарии оболочки
  • Эффективное использование dd (буфер много блоков, процесс по одному)
  • Проверьте, имеют ли файлы в определенном каталоге надлежащее расширение?
  • Извлечь часть строки в сценарии bash
  • Как написать функцию псевдонима, чтобы dd отображал индикатор выполнения?
  • Как передать содержимое файла параметру / параметру функции
  • Bash Mysql Command Замена Login Failure
  • 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 

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

    Linux и Unix - лучшая ОС в мире.