Заменить всю строку, содержащую строку, с помощью Sed

у меня есть текстовый файл, который имеет определенную линию что-то вроде

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

мне нужно заменить всю строку с

This line is removed by the admin.

ключевое слово поиска TEXT_TO_BE_REPLACED

мне нужно написать shell-скрипт для этого. Как я могу достичь этого, используя sed?

10 ответов


можно использовать изменить команда для замены всей строки и -i флаг для внесения изменений на месте. Например, с помощью GNU sed:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

вам нужно использовать wildards (.*) до и после замены всей строки:

sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'

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

  • моя версия sed не нравится -i С расширением нулевой длины
  • синтаксис c\ команда странная, и я не мог заставить ее работать
  • Я не понимал, что некоторые из моих проблем исходят от unescaped slashes

Итак, вот решение, которое я придумал, которое, я думаю, должно работать для большинства случаев:

function escape_slashes {
    sed 's/\//\\//g' 
}

function change_line {
    local OLD_LINE_PATTERN=; shift
    local NEW_LINE=; shift
    local FILE=

    local NEW=$(echo "${NEW_LINE}" | escape_slashes)
    sed -i .bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
    mv "${FILE}.bak" /tmp/
}

так использование образца чтобы исправить проблему:

change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile

ответ выше:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

отлично работает, если строка/строка замены не является переменной.

проблема в том, что на Redhat 5 \ после c уходит $. Двойной \ тоже не сработало (по крайней мере, на Redhat 5).

через хит и суд, я обнаружил, что \ после c является избыточным, если строка/строка замены является только одной строкой. Поэтому я не использовал \ после c, используется a переменная, как одна линия замены, и это была радость.

код будет выглядеть примерно так:

sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo

обратите внимание на использование двойных кавычек вместо одинарных кавычек.


в моем makefile я использую это:

@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md

PS:НЕ забудьте, что-i изменяет фактически текст в файле... поэтому, если шаблон, который вы определили как "ревизия", изменится, вы также измените шаблон для замены.

пример:

Abc-проект, написанный Джоном Доу

редакции: 1190

поэтому, если вы установите шаблон "Revision: 1190", это, очевидно, не то же самое, что вы определили их как "ревизию:" только...


bash-4.1$ new_db_host="DB_HOSTNAME=good replaced with 122.334.567.90"
bash-4.1$ 
bash-4.1$ sed -i "/DB_HOST/c $new_db_host" test4sed
vim test4sed
'
'
'
DB_HOSTNAME=good replaced with 122.334.567.90
'

он работает


все ответы, представленные до сих пор, предполагают, что вы знаете что-то о заменяемом тексте, что имеет смысл, так как это то, что спросил OP. Я предоставляю ответ, который предполагает, что вы ничего не знаете о заменяемом тексте и что в файле может быть отдельная строка с тем же или подобным содержимым, которое вы не хотите заменять. Кроме того, я предполагаю, что вы знаете номер строки строки, которую нужно заменить.

следующие примеры демонстрируют удаление или изменение текста по определенным номерам строк:

# replace line 17 with some replacement text and make changes in file (-i switch)
# the "-i" switch indicates that we want to change the file. Leave it out if you'd
#   just like to see the potential changes output to the terminal window.
# "17s" indicates that we're searching line 17
# ".*" indicates that we want to change the text of the entire line
# "REPLACEMENT-TEXT" is the new text to put on that line
# "PATH-TO-FILE" tells us what file to operate on
sed -i '17s/.*/REPLACEMENT-TEXT/' PATH-TO-FILE

# replace specific text on line 3
sed -i '3s/TEXT-TO-REPLACE/REPLACEMENT-TEXT/'

cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file    
done 

файл find_replace содержит 2 столбца, c1 с шаблоном для соответствия, c2 с заменой, цикл sed заменяет каждую строку, содержащую один из шаблонов переменной 1


это похоже на выше одного..

sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'

Я очень часто использую regex для извлечения данных из файлов, которые я только что использовал, чтобы заменить буквальную цитату \" С // ничего :-)

cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed  s/\"//g  | cut -d, -f1 > list.txt