Удалить строку, если в одной строке найдены два шаблона

Удалить строку, если в одной строке найдены два шаблона

Я хотел бы удалить строку из текстового файла ( ), если в ней найдены input.txtдва шаблона ( string1и )string2такой жестрока, используя sed.

Я пытаюсь: sed -i "/\b\(string1\|string2\)\b/d" input.txt, но это удаляет строки, содержащие string1OR string2.

решение1

sed -i "/string1.*string2\|string2.*string1/d" input.txt

Это удалит любую строку, где string1 появляется перед string2, ИЛИ string2 появляется перед string1. Обе строки должны быть в строке, в любом порядке, чтобы строка была удалена.

решение2

sed -ie '/string1/!b' -e '/string2/d' file.txt

Это удалит строки, содержащие string1и string2независимо от порядка (они могут даже перекрываться, как при поиске foobarв barbazстроке, содержащей foobarbaz).

-iвыше — расширение GNU. Другое решение, специфичное для GNU¹:

awk -i /usr/share/awk/inplace.awk '!(/string1/ && /string2/)' file.txt

В переносимом варианте вы, вероятно, использовали бы perlздесь:

perl -ni -e 'print unless /string1/ && /string2/'

¹не использовать-i inplaceas сначала gawkпытается загрузить inplaceрасширение (как inplaceили inplace.awk) из текущего рабочего каталога, где кто-то мог разместить вредоносное ПО. Путь расширения, inplaceпоставляемого с, gawkможет различаться в зависимости от системы, см. выводgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

решение3

С использованиемРаку(ранее известный как Perl_6)

~$ raku -ne '.put unless .match(/ foobar / & / barbaz / ) ;'   file

ИЛИ

~$ raku -ne '.put unless grep({ / foobar / & / barbaz / }, $_ ) ;'   file

Выше приведены два общих способа выполнения задачи OP с помощью Raku. Примечание grepв Raku похоже на grepPerl, за исключением того, что после блока требуется запятая. Вы также можете использовать .grepвызов метода вместо этого и не беспокоиться о написании $_внутри скобок.

Любой из приведенных выше примеров кода удалит строки, содержащие две строки,независимо от порядка И независимо от того, перекрываются ли строки.Например:

Пример ввода:

1  foo
2  bar
3  baz
4  foobar
5  foobaz
6  barbaz
7  foobar foobaz
8  foobaz barbaz
9  foobar barbaz
10 foobar foobaz barbaz
11 foobaz barbaz foobar
12 barbaz foobar foobaz
13 foobarbaz

Пример выходных данных (пример кода выше):

1  foo
2  bar
3  baz
4  foobar
5  foobaz
6  barbaz
7  foobar foobaz
8  foobaz barbaz

Приведенный выше код удаляет строки с 9 по 13, включая строку 13, foobarbazкоторая содержит перекрывающиеся string1 и string2. Если вам нужно удалить строки, которые появляются в определенном порядке (и без перекрытия), Raku может сделать это тоже:

~$ raku -ne '.put unless m/foobar .* barbaz/;'  file

Выше удаляются строки 9 и 10: foobar barbazи foobar foobaz barbaz.


Обратите внимание, что с помощью регулярных выражений Raku выможетобнаружить две строки, которые перекрываются, с параметром/наречием :overlap(или :ov). См. первую ссылку ниже.


https://docs.raku.org/language/regexes#Overlap
https://docs.raku.org/language/regexes
https://raku.org

Связанный контент