Удаление строк в текстовом файле, содержащих определенную строку

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

14 ответов


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

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

чтобы напрямую изменить файл:

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

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

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

для пользователей Mac OS X и FreeBSD:

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

есть много других способов удалить строки с определенной строкой, кроме 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

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

например

sed -i '/pattern/d' filename      

или

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

первая команда занимает в 3 раза больше времени на моей машине.


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

sed --in-place '/some string here/d' yourfile

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

ex +g/match/d -cwq file

где:

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

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


разница с sed это:

sed это Stream Эдitor, а не редактор файлов.BashFAQ

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


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

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

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

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

Я выбрал '' отсюда комментарий.

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


чтобы получить inplace как результат с grep можно сделать так:

echo "$(grep -v "pattern" filename)" >filename

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

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

вот команды и тайминги:

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


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

 grep -v 'pattern' filename

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


echo -e "/thing_to_delete\ndd3:x\n" | vim file_to_edit.txt


perl -i    -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3

первая команда редактирует файл(ы) inplace (-i).

вторая команда делает то же самое, но сохраняет копию или резервную копию оригинального файла(ов) путем добавления .БК к именам файлов (.БК можно изменить на что угодно).


cat filename | grep -v "pattern" > filename.1
mv filename.1 filename

на всякий случай, если кто-то хочет сделать это для точного соответствия строк, вы можете использовать -w флаг в grep-w для целого. То есть, например, если вы хотите удалить строки с номером 11, но сохраните строки с номером 111:

-bash-4.1$ head file
1
11
111

-bash-4.1$ grep -v "11" file
1

-bash-4.1$ grep -w -v "11" file
1
111

Он работает с -f флаг, если вы хотите исключить сразу несколько точных шаблонов. Если "черный список" - это файл с несколькими шаблонами в каждой строке, который вы хотите удалить из "файла":

grep -w -v -f blacklist file