
У меня есть большой файл, в котором есть специальные символы. Там есть многострочный код, который я хочу заменить на sed
.
Этот:
text = "\
------ ------\n\n\
This message was automatically generated by email software\n\
The delivery of your message has not been affected.\n\n\
------ ------\n\n"
Нужно превратить в это:
text = ""
Я попробовал следующий код, но безуспешно:
sed -i '/ text = "*/ {N; s/ text = .*affected.\./ text = ""/g}' /etc/exim.conf
Он ничего не заменяет и не отображает никаких сообщений об ошибках.
Я пробовал с этим, но все, что я пробовал, не работает.
решение1
Perl спешит на помощь:
perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
-i~
отредактирует файл «на месте», оставив резервную копию-0777
читает весь файл сразу, а не построчно
Подстановка s///
работает так же, как и в sed (т.е. она сопоставляет все, text = "
за чем следует что угодно, кроме двойных кавычек, много раз вплоть до двойной кавычки), но в этом случае она работает со всем файлом.
решение2
Вам нужно проверить шаблонное пространство и продолжать вставлять N
дополнительную линию, если она не совпадает, например
sed '/text = "/{ # if line matches text = "
:b # label b
$!N # pull in the next line (if not the last one)
/"$/!bb # if pattern space doesn't end with " go to label b
s/".*"/""/ # else remove everything between the quotes
}' infile
с gnu sed
вы можете написать это как
sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile
Хотя это не очень эффективно, лучше просто выделить диапазон /text = "/,/"/
, изменить первую строку и удалить остальное:
sed '/text = "/,/"/{ # in this range
/text = "/!d # delete all lines not matching text = "
s/\\/"/ # replace the backslash with quotes (this is only
}' infile # executed if the previous d wasn't executed)
Опять же, gnu sed
вы можете записать это в одну строку:
sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile
решение3
"
Лично я бы сделал это в Perl. Если предположить, что до закрытия нет "
, можно сделать:
perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file
The -0
поглощает весь файл, считывая его в память. The -p
означает "печатать каждую строку (здесь "строкой" будет весь файл) после применения скрипта, заданного -e
". Сам скрипт является простым оператором подстановки. Он захватит строку, text
за которой следуют 0 или более пробельных символов, =
и снова 0 или более пробельных символов ( text\s*=\s*
) и сохранит ее как $1
. Затем он заменит захваченный шаблон, а также самую короткую найденную им строку в кавычках на шаблон ( $1
) и ""
. s
Флаг заставляет .
сопоставлять новые строки.