Как удалить строки из текстового файла, который имеет определенное значение в столбце через входной файл?

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

data.txt

ESP|041336|46566|NY|CA ESP|041337|46566|NY|CA ESP|041338|46566|NY|CA ESP|041339|46566|NY|CA ESP|041340|46566|NY|CA ESP|041341|46566|NY|CA 

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

input.txt

 041337 041338 041339 

Я пытаюсь удалить строки, которые имеют значения из input.txt во втором столбце.

Ожидаемый результат

 ESP|041336|46566|NY|CA ESP|041340|46566|NY|CA ESP|041341|46566|NY|CA 

Я пытаюсь использовать grep здесь, как показано ниже.

 grep -vfw input.txt data.txt > output.txt 

Это не удаляет столбцы, но выдает ошибку «Нет такого файла или каталога» и возвращает пустой файл.

Если вы хотите ограничить сравнение только вторым полем с разделителями, вы можете использовать awk вместо grep:

 $ awk -F'|' 'NR==FNR {a[$1]++; next} !($2 in a)' input.txt data.txt > output.txt $ cat output.txt ESP|041336|46566|NY|CA ESP|041340|46566|NY|CA ESP|041341|46566|NY|CA 

Опция -f ожидает имя файла. Как вы пишете, именем файла является текст, следующий за f , в -vfw , другими словами, это w .

Вы должны поместить опцию, которая принимает аргумент в конце (за исключением tar , который использует странный вариант парсинга).

Любой из них должен работать.

 grep -v -w -f input.txt data.txt > output.txt grep -vwf input.txt data.txt > output.txt grep -vwfinput.txt data.txt > output.txt 

Примечание: точное сообщение об ошибке, которое вы всегда должны указывать полностью, когда задаете вопрос, упоминает имя w .

grep: w : Нет такого файла или каталога

 sed -nE ' /\|/!{H;1h;d;} G /^[^|]+\|([^|]+)\|.*\n\1(\n|$)/!P ' input.txt data.txt 

Результат:

 ESP|041336|46566|NY|CA ESP|041340|46566|NY|CA ESP|041341|46566|NY|CA 

Комментарии:

  • Сохраните строки input.txt в удерживающем пространстве, так как в них нет канала. /\|/! Эти строки разделены символами новой строки в области удержания.

  • Для строк данных мы добавляем область удержания к пространству шаблона, затем пытаемся найти второе поле с разделителями канала. Если он не найден, распечатайте часть перед первой новой строкой в ​​пространстве шаблона P

    /^[^|]+\|([^|]+)\|.*\n\1(\n|$)/ выражение, /^[^|]+\|([^|]+)\|.*\n\1(\n|$)/ соответствует /^[^|]+\|([^|]+)\|.*\n\1(\n|$)/ шаблона, если второе | Поле -delimited в строке данных (из data.txt ) соответствует одной из входных строк, которые находятся в конце пространства шаблона, разделенного символами новой строки. Он имеет условие ИЛИ в конце, чтобы позаботиться о сценарии, когда соответствующий шаблон был последней строкой файла input.txt .

Предполагается, что версия GNU sed с расширенными регулярными выражениями позволяет уменьшить шум в линии.