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

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

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

  • Удаление подстрок из переменной оболочки
  • for loop для запуска команды для всех файлов в папке
  • сравнить файлы по строкам и создать новое одно bash-программирование
  • KSH / BASH Максимальный размер массива
  • Сценарий оболочки останавливается автоматически примерно через 1 минуту
  • Найти все папки в каталоге с тем же контентом
  • Вот пример, на который я надеюсь проиллюстрировать, что мне нужно:

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

  • Умножьте столбец с помощью awk
  • AWK: передача переменных оболочки awk
  • Вывод Shell Script не записывается в файл должным образом
  • Как сопоставить текст между строкой и пробелом
  • Объединение двух файлов, соответствующих двум столбцам с несоответствиями и в каждой соответствующей строке, замените второй столбец из файла 1 на 6-й столбец в файле 2
  • Установить команду, если команда не существует
  • 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 - лучшая ОС в мире.