Удаление строк в текстовом файле, содержащих определенную строку
Как бы я использовал 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 раза больше времени на моей машине в любом случае.
вы можете использовать
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
будет печатать только кроме вашего шаблона (что означает инвертировать матч).
perl -i -nle'/regexp/||print' file1 file2 file3 perl -i.bk -nle'/regexp/||print' file1 file2 file3
первая команда редактирует файл(ы) inplace (-i).
вторая команда делает то же самое, но сохраняет копию или резервную копию оригинального файла(ов) путем добавления .БК к именам файлов (.bk может быть изменен на что угодно).
просто в случае если кто-то хочет сделать это для точного совпадения строк, вы можете использовать
-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