Ответ 1
Вы можете использовать команду изменения, чтобы заменить всю строку, и флаг -i
, чтобы внести изменения на месте. Например, используя GNU sed:
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
У меня есть текстовый файл, который имеет определенную строку, похожую на
sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext
Мне нужно заменить всю строку выше на
This line is removed by the admin.
Ключевое слово поиска TEXT_TO_BE_REPLACED
Мне нужно написать оболочку script для этого. Как я могу достичь этого, используя sed
?
Вы можете использовать команду изменения, чтобы заменить всю строку, и флаг -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./'
Принятый ответ не работал у меня по нескольким причинам:
-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
Ответ выше:
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
Обратите внимание на использование двойных кавычек вместо одиночных кавычек.
Все ответы, представленные до сих пор, предполагают, что вы знаете что-то о заменяемом тексте, что имеет смысл, поскольку это то, что задал ОП. Я предоставляю ответ, предполагающий, что вы ничего не знаете о тексте, который нужно заменить, и что в файле может быть отдельная строка с тем же или похожим содержимым, которое вы не хотите заменять. Кроме того, я предполагаю, что вы знаете номер строки строки, которую нужно заменить.
Следующие примеры демонстрируют удаление или изменение текста по определенным номерам строк:
# 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/'
для манипулирования конфигурационными файлами
я придумал это решение, вдохновленное ответом skensell
configLine [searchPattern] [replaceLine] [filePath]
это будет:
Функция:
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/...
В моем make файле я использую это:
@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md
PS: НЕ НЕ забыть, что -i действительно меняет текст в файле... поэтому, если шаблон, который вы определили как "Редакция", изменится, вы также измените шаблон для замены,
Пример вывода:
Abc-Project, написанный Джоном Доу
Просмотр: 1190
Итак, если вы установите шаблон "Редакция: 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
'
он отлично работает
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./'
Ниже команда работает для меня. Который работает с переменными
sed -i "/\<$E\>/c $D" "$B"
Я очень часто использую regex для извлечения данных из файлов, которые я использовал, чтобы заменить литеральную цитату \"
на //
ничего:-)
cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed s/\"//g | cut -d, -f1 > list.txt