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


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

14 1374

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.SE и спецификации POSIX для ex.


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

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

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

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

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

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

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

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

здесь следует отметить использование двойные кавычки in "/$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).

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

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