Як я можу використовувати sed для видалення всіх рядків у текстовому файлі, що містять певний рядок?
Як я можу використовувати sed для видалення всіх рядків у текстовому файлі, що містять певний рядок?
Відповіді:
Щоб видалити рядок і роздрукувати вихідний стандарт у стандартному режимі:
sed '/pattern to match/d' ./infile
Щоб безпосередньо змінити файл - не працює з BSD sed:
sed -i '/pattern to match/d' ./infile
Те саме, але для BSD sed (Mac OS X і FreeBSD) - не працює з sed GNU:
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 як in sed -i '/pattern to match/d' ./infile
. Зауважте, що -i
прапор вимагає sed GNU і не є портативним
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
реальні 0м9.294с. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
реальні 0м13.671с. (Для менших файлів різниця більша.)
Ви можете використовувати sed для заміни рядків у файлі. Однак, здається, це набагато повільніше, ніж використання grep для зворотного у другий файл, а потім переміщення другого файлу над оригіналом.
напр
sed -i '/pattern/d' filename
або
grep -v "pattern" filename > filename2; mv filename2 filename
Перша команда все-таки займає 3 рази більше часу на моїй машині.
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 трем ED ED itor , а не редактор файлів. 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
буде надруковано лише інший, ніж ваш візерунок (це означає перевернути відповідність).
Щоб отримати такий результат, grep
ви можете зробити це:
echo "$(grep -v "pattern" filename)" >filename
bash
оболонки або подібного (не tcsh
).
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Перша команда редагує файл (и) inplace (-i).
Друга команда робить те саме, але зберігає копію чи резервну копію вихідних файлів, додаючи .bk до імен файлів (.bk можна змінити на будь-що).
На всякий випадок, якщо хтось захоче зробити це для точних відповідностей рядків, ви можете використовувати -w
прапор у великій точці - 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.
vs.-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
можуть. Використовуючи його в сценарії, звичайним способом для цього є використання printf
для передачі команд на нього:
printf "%s\n" "g/pattern/d" w | ed -s filename
або з гередоком:
ed -s filename <<EOF
g/pattern/d
w
EOF