
Я хотел бы удалить строку из текстового файла ( ), если в ней найдены input.txt
два шаблона ( string1
и )string2
такой жестрока, используя sed
.
Я пытаюсь:
sed -i "/\b\(string1\|string2\)\b/d" input.txt
, но это удаляет строки, содержащие string1
OR 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 inplace
as сначала 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 похоже на grep
Perl, за исключением того, что после блока требуется запятая. Вы также можете использовать .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