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

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

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

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

This line is removed by the admin.

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

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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

    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

Ответ 4

Ответ выше:

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

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

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

Через хит и пробную версию я обнаружил, что \ после c является избыточным, если ваша строка-строка - только одна строка. Поэтому после c я не использовал \, использовал переменную как одну заменяющую строку, и это было радостью.

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

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

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

Ответ 5

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

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

# 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/'

Ответ 6

для манипулирования конфигурационными файлами

я придумал это решение, вдохновленное ответом skensell

configLine [searchPattern] [replaceLine] [filePath]

это будет:

  • создайте файл, если он не существует
  • заменить всю строку (все строки), где searchPattern соответствует
  • добавьте replaceLine в конец файла, если шаблон не был найден

Функция:

function configLine {
  local OLD_LINE_PATTERN=$1; shift
  local NEW_LINE=$1; shift
  local FILE=$1
  local NEW=$(echo "${NEW_LINE}" | sed 's/\//\\\//g')
  touch "${FILE}"
  sed -i '/'"${OLD_LINE_PATTERN}"'/{s/.*/'"${NEW}"'/;h};${x;/./{x;q100};x}' "${FILE}"
  if [[ $? -ne 100 ]] && [[ ${NEW_LINE} != '' ]]
  then
    echo "${NEW_LINE}" >> "${FILE}"
  fi
}

сумасшедшая магия статуса выхода исходит от fooobar.com/questions/181428/...

Ответ 7

В моем make файле я использую это:

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

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

Пример вывода:

Abc-Project, написанный Джоном Доу

Просмотр: 1190

Итак, если вы установите шаблон "Редакция: 1190", это явно не то же самое, что вы определили их как "Редакция:"...

Ответ 8

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
'

он отлично работает

Ответ 9

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

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

Ответ 10

Это похоже на предыдущее.

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

Ответ 11

Ниже команда работает для меня. Который работает с переменными

sed -i "/\<$E\>/c $D" "$B"

Ответ 12

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

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