Удалить строки в текстовом файле, которые содержат определенную строку - PullRequest
1574 голосов
/ 23 марта 2011

Как бы я использовал sed, чтобы удалить все строки в текстовом файле, которые содержат определенную строку?

Ответы [ 14 ]

2414 голосов
/ 23 марта 2011

Чтобы удалить строку и распечатать вывод на стандартный вывод:

sed '/pattern to match/d' ./infile

Чтобы напрямую изменить файл - не работает с BSD sed:

sed -i '/pattern to match/d' ./infile

То же самое, но дляBSD sed (Mac OS X и FreeBSD) - не работает с GNU sed:

sed -i '' '/pattern to match/d' ./infile

Чтобы напрямую изменить файл (и создать резервную копию) - работает с BSD и GNU sed:

sed -i.bak '/pattern to match/d' ./infile
586 голосов
/ 24 марта 2011

Существует много других способов удаления строк с определенной строкой, кроме sed:

AWK

awk '!/pattern/' file > temp && mv temp file

Рубин (1,9 +)

ruby -i.bak -ne 'print if not /test/' file

Perl

perl -ni.bak -e "print unless /pattern/" file

Shell (bash 3.2 и более поздние версии)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

GNU grep

grep -v "pattern" file > temp && mv temp file

И, конечно, sed (обратная печать выполняется быстрее, чем фактическое удаление):

sed -n '/pattern/!p' file
222 голосов
/ 02 ноября 2012

Вы можете использовать sed для замены строк в файле.Однако, это кажется намного медленнее, чем использование grep для инверсии во второй файл и затем перемещение второго файла поверх оригинала.

например

sed -i '/pattern/d' filename      

или

grep -v "pattern" filename > filename2; mv filename2 filename

Первая команда на моей машине все равно дольше в 3 раза.

65 голосов
/ 02 января 2015

Простой способ сделать это с GNU sed:

sed --in-place '/some string here/d' yourfile
30 голосов
/ 17 октября 2015

Вы можете рассмотреть возможность использования ex (который является стандартным редактором на основе команд Unix):

ex +g/match/d -cwq file

где:

  • + выполняет указанную команду Ex (man ex), так же как -c, которая выполняет wq (запись и выход)
  • g/match/d - команда Ex для удаления строк с указанным match, см .: Мощность g

Приведенный выше пример представляет собой POSIX-совместимый метод для редактирования файла на месте согласно этой записи в Unix.SE и Спецификации POSIX для ex.


Разница с sed заключается в том, что:

sed является S tream ED итор, а не редактор файлов. BashFAQ

Если вам не нравится непортативный код, накладные расходы ввода-вывода и некоторые другиеплохие побочные эффекты.Поэтому в основном некоторые параметры (например, на месте / -i) являются нестандартными расширениями FreeBSD и могут быть недоступны в других операционных системах.

14 голосов
/ 09 марта 2016

Я боролся с этим на Mac.Кроме того, мне нужно было сделать это с помощью замены переменных.

Поэтому я использовал:

sed -i '' "/$pattern/d" $file

, где $file - файл, в котором требуется удаление, и $pattern - это шаблон для сопоставления для удаления.

Я выбрал '' из этого комментария .

Здесь следует отметить использование doubleцитаты в "/$pattern/d".Переменная не будет работать, если мы будем использовать одинарные кавычки.

13 голосов
/ 19 марта 2017

Я сделал небольшой тест с файлом, который содержит приблизительно 345 000 строк. В этом случае путь с grep кажется примерно в 15 раз быстрее, чем метод sed.

Я пробовал как с настройкой LC_ALL = C, так и без нее, кажется, что изменение времени существенно не изменилось. Строка поиска (CDGA_00004.pdbqt.gz.tar) находится где-то в середине файла.

Вот команды и время:

time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt

real    0m0.711s
user    0m0.179s
sys     0m0.530s

time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt

real    0m0.105s
user    0m0.088s
sys     0m0.016s

time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )

real    0m0.046s
user    0m0.014s
sys     0m0.019s
12 голосов
/ 13 июня 2015

Чтобы получить такой же результат, как с grep, вы можете сделать это:

12 голосов
/ 28 марта 2015

Вы также можете использовать это:

 grep -v 'pattern' filename

Здесь -v будет печатать только ваш шаблон (что означает инвертированное совпадение).

8 голосов
/ 25 августа 2016
...