У меня есть большой файл, и я хотел бы удалить из него все строки, содержащие точную строку, указанную в другом файле. Однако строка должна точно совпадать (извините, я не знаю, как это лучше описать).
Вот файл:
[email protected],name,surname,city,state
[email protected],name,surname,city,state
[email protected],name,surname,city,state
[email protected],name,surname,city,state
А вот примерный список для фильтрации:
[email protected]
[email protected]
Желаемый результат:
[email protected],name,surname,city,state
[email protected],name,surname,city,state
Я попытался сделать это, используя следующее:
grep -v -f 2.txt 1.txt > 3.txt
Однако это производит вывод:
[email protected],name,surname,city,state
Я предполагаю, что это происходит потому, что «[email protected]» содержит «[email protected]». Я искал способ включить начало строки, но не нашел ничего подходящего.
Я открыт для чего-то другого, кроме grep, я использовал grep, потому что не мог понять это по-другому.
Если вы используете GNU grep, добавьте опцию -w
.
Если вы хотите печатать только строки из первого файла, которые does not
содержат данные из второго файла в первом поле, то это должно быть сделано:
$cat file
[email protected],name,surname,city,state
[email protected],name,surname,city,state
[email protected],name,surname,city,state
[email protected],name,surname,city,state
$cat filter
[email protected]
[email protected]
awk -F, 'NR==FNR {a[$0]++;next} !($1 in a)' filter file
[email protected],name,surname,city,state
[email protected],name,surname,city,state
Для каждой строки в filter
создается массив a
с именем и значением 1
Лайк a[[email protected]]=1
и a[[email protected]]=1
Затем awk
построчно проверяйте file
массив, давая
a[[email protected]]=1
a[[email protected]]=
a[[email protected]]=1
a[[email protected]]=
Затем выведите всю строку из file
без 1
[email protected],name,surname,city,state
[email protected],name,surname,city,state
Работал отлично и с двумя массивными файлами, которые я использовал. Большое спасибо за это.
Для этого конкретного случая -- обработайте первый файл, построив ассоциативный массив со строками фильтра, являющимися индексом. В последующих файлах проверьте, нет ли данной строки в индексах массива — действие шаблона по умолчанию — печать.
awk -F, -v OFS=, '
BEGIN { split("", m) }
NR==FNR { m[$0] = ""; next }
!($1 in m)
' filter.txt file.txt
Но... если мы хотим отфильтровать любое вхождение строки в любом месте строки (неограниченное точное совпадение), нам нужно сделать что-то менее умное и более грубое:
awk '
BEGIN {
split("", m)
n=0
}
NR==FNR {
m[n++] = $0
next
}
{
for (i=0; i<n; ++i) {
if (index($0, m[i]))
next
}
print
}
' filter.txt file.txt
Обратите внимание, что если фильтр содержит непечатаемые символы (например, окончания строк, отличные от Unix), нам нужно будет иметь дело с ними, отфильтровав их (например, с помощью sub(/\r/, "")
).
Предполагая, что ваш входной файл содержит [email protected]
, а не [email protected]
(возможно, опечатка)
$ grep -vw -f 2.txt 1.txt
[email protected],name,surname,city,state
[email protected],name,surname,city,state
-w, --word-regexp - The expression is searched for as a word (as if surrounded by
[[:<:]]' and
[[:>:]]';
Это может быть несколько опасно, так как фильтр ищет не только в первом поле файла, но и везде в строке. Поэтому, если слово находится в конце, оно также удаляет всю строку. Бывший. он удалит эту строку [email protected],name,surname,city,state,[email protected]
@Jotne, ОП не указал правило поиска "в поле первый файла"
Правда, именно поэтому OP должен прочитать мой комментарий и увидеть, что это решение действительно удаляет строку, если данные фильтра находятся где-либо в строке, и он ищет только первое поле. Ваше решение может подойти для ОП.
@Jotne хорошо, подождем реакции ОП
Извините за поздний ответ - адрес электронной почты находится только в первом поле, поэтому он работает должным образом. Однако из-за размера входных данных это довольно быстро привело к ошибке памяти.
[email protected] != [email protected]