Как бы я использовал sed, чтобы удалить все строки в текстовом файле, которые содержат определенную строку?
Как бы я использовал sed, чтобы удалить все строки в текстовом файле, которые содержат определенную строку?
Ответы:
Чтобы удалить строку и распечатать вывод на стандартный вывод:
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
sed '/pattern to match/d' ./infile > ./newfile
либо, если вы хотите выполнить редактирование на месте, тогда вы можете добавить -i
флаг в sed, как в sed -i '/pattern to match/d' ./infile
. Обратите внимание, что -i
флаг требует GNU sed и не является переносимым
sed -i.backup '/pattern to match/d' ./infile
) Это помогло мне с правками на месте.
sed
тем, которые не контролируются версиями.
sed -i '' '/pattern/d' ./infile
.
Есть много других способов удалить строки с определенной строкой, кроме sed
:
awk '!/pattern/' file > temp && mv temp file
ruby -i.bak -ne 'print if not /test/' file
perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
grep -v "pattern" file > temp && mv temp file
И конечно sed
(обратная печать выполняется быстрее, чем фактическое удаление):
sed -n '/pattern/!p' file
sed
пример имеет различное поведение, он только отбирает! это должно быть что-то вроде sed -n -i '/pattern/!p' file
.
grep -v "pattern" file > temp; mv temp file
это может относиться к некоторым другим примерам в зависимости от возвращаемого значения.
seq -f %f 10000000 >foo.txt
. sed d: time sed -i '' '/6543210/d' foo.txt
реальный 0m9.294s. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
реальный 0m13.671s. (Для файлов меньшего размера разница больше.)
Вы можете использовать sed для замены строк в файле. Тем не менее, это выглядит намного медленнее, чем использование grep для обратного преобразования во второй файл, а затем перемещение второго файла поверх оригинала.
например
sed -i '/pattern/d' filename
или
grep -v "pattern" filename > filename2; mv filename2 filename
В любом случае, первая команда на моей машине занимает в три раза больше времени.
sed '/pattern/d' filename > filename2; mv filename2 filename
Самый простой способ сделать это с помощью GNU sed
:
sed --in-place '/some string here/d' yourfile
-r
вариант (или -E
, в зависимости от вашей версии). Это позволяет использовать регулярные выражения метасимволов +
, ?
, {...}
и (...)
.
Вы можете рассмотреть возможность использования 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 и могут быть недоступны в других операционных системах.
man ex
это дает мне человек за vim
это , кажется , ex
является частью Vim ... если я понял правильно , что означает , что синтаксис шаблона для match
является vimregex.com , который похож , но отличается от POSIX и PCRE вкусов?
:g
является POSIX-совместимой командой с некоторыми небольшими отличиями . Я предполагаю, что PCRE был основан на этом.
Я боролся с этим на Mac. Плюс, мне нужно было сделать это с помощью замены переменных.
Поэтому я использовал:
sed -i '' "/$pattern/d" $file
где $file
файл, в котором требуется удаление, и $pattern
шаблон, который необходимо сопоставить для удаления.
Я выбрал ''
из этого комментария .
Дело в том, чтобы отметить здесь является использование двойных кавычек в "/$pattern/d"
. Переменная не будет работать, когда мы используем одинарные кавычки.
sed
требует параметр после -i
, поэтому, если вы не хотите создавать резервную копию, вам все равно нужно добавить пустую строку:-i ''
sed -i "/$pattern/d" $file
. Спасибо за ваш ответ.
Я сделал небольшой тест с файлом, который содержит примерно 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
Вы также можете использовать это:
grep -v 'pattern' filename
Здесь -v
будет печататься только ваш шаблон (это означает инвертированное совпадение).
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Первая команда редактирует файл (ы) на месте (-i).
Вторая команда делает то же самое, но сохраняет копию или резервную копию исходного файла (ов), добавляя .bk к именам файлов (.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
-w, --word-regexp Select only those lines containing matches that form whole words.
против-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
показать обработанный текст в консоли
cat filename | sed '/text to remove/d'
сохранить обработанный текст в файл
cat filename | sed '/text to remove/d' > newfile
добавить обработанную текстовую информацию в существующий файл
cat filename | sed '/text to remove/d' >> newfile
чтобы обработать уже обработанный текст, в этом случае удалите больше строк из того, что было удалено
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
| more
покажет текст кусков одной страницы за один раз.
Вы можете использовать хороший старый , ed
чтобы редактировать файл аналогичным образом в ответ , который использует ex
. Большая разница в этом случае заключается в том, что ed
команды принимаются через стандартный ввод, а не как аргументы командной строки, такие как ex
can. При использовании его в скрипте, обычный способ приспособиться к этому - использовать printf
для передачи ему команд:
printf "%s\n" "g/pattern/d" w | ed -s filename
или с наследственностью:
ed -s filename <<EOF
g/pattern/d
w
EOF