Я пытаюсь найти эти три строчки:
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
и замените их на:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
Когда я пытаюсь
sudo sed -i 's:<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml
Не находит, тоже пробовал вставить \ n, но все равно не вышло:
sudo sed -i 's:<!--\n <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />\n -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml
Они не вызывают ошибок, просто не раскомментируют строку. Любой совет поможет спасибо!
Sed работает построчно. Его можно заставить работать с несколькими линиями, но он не был разработан таким образом - и, на мой взгляд, это определенно видно, когда вы пытаетесь использовать это. Но если вы решите пойти по этому пути, вам, вероятно, придется использовать регистры. Ознакомьтесь с некоторыми решениями https://stackoverflow.com/questions/1251999/sed-how-can-i-replace-a-newline-n чтобы увидеть, как это можно сделать.
Я предпочитаю использовать perl вместо sed для такого рода задач (я имею в виду многострочную). Шаблон, который вы должны добавить перед поиском и заменой (BEGIN...
) не очевидно, но мне кажется, что регулярное выражение чище:
perl -i.bak -pe 'BEGIN{undef $/;} s/<!--string-->/string/smg' file.xml
Или, используя группировку, чтобы сократить выражение и позволить вам использовать там регулярное выражение:
perl -i.bak -pe 'BEGIN{undef $/;} s/<!--(string_or_regex)-->/\1/smg' file.xml
Он должен работать как с вхождениями с новой строкой, так и без нее между маркерами комментариев и кодом, который нужно раскомментировать.
Адаптировано из:
https://stackoverflow.com/questions/1030787/multiline-search-replace-with-perl
sed читает каждую строку по очереди, поэтому он никогда не будет соответствовать многострочному шаблону, если вы не подтолкнете его в правильном направлении. В N
команда считывает одну строку из ввода и добавляет ее в пространство шаблонов.
sed -i -e '/^<!--$/ {
N; /\n<Connector port="8009" protocol="AJP\/1\.3" redirectPort="8443" \/>$/ {
N; /\n-->$/ {
s/^<!--\n//; s/\n-->$//
}
}
}' /myfile.xml
Возможно, если вам нужна другая команда, кроме s
, тогда вам следует отказаться от sed и перейти на awk или perl. Вот немного более гибкий фрагмент Perl, который справляется с многострочными комментариями в более общем виде.
perl -i -pe '
if (/<!--/) { $_ .= <> while !/-->/;
s[<!--\n(<Connector port="8009" protocol="AJP/1\.3" redirectPort="8443" />)\n-->][$1];
}' /myfile.xml
Вот описание многострочных команд в SED: http://docstore.mik.ua/orelly/unix/sedawk/ch06_01.htm
Это боль в заднице. Вы можете последовать совету Эдуардо и использовать perl -i -p -e
вместо.
/<\!--/
: соответствующая строка:X
: это метка для команды ветви "b"/-->/
: соответствующая строкаs@...@...@p
: strip "<! -", "->" и распечатать результатd
: удалить шаблонное пространство и начать новый циклN
: если не совпадает с / -> /, добавьте строкуbX
: переход к: метке Xp
: просто напечатайте строку, которая не соответствует / <! - /sed -rn '
/<!--/ {
:X
/-->/ {
s@<!--\s*(<.+/>)\s*-->@\1@p
d
}
N
bX
};p'
и этот второй метод представляет собой простую дословную замену копирования и вставки для обычных текстовых файлов небольшого размера (требуется файл сценария оболочки)
#!/bin/bash
# copy & paste content that you want to substitute
AA=$( cat <<\EOF | sed -z -e 's#\([][^$*\.#]\)#\\\1#g' -e 's#\n#\\n#g'
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
EOF
)
BB=$( cat <<\EOF | sed -z -e 's#\([&\#]\)#\\\1#g' -e 's#\n#\\n#g'
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
EOF
)
sed -z -i 's#'"${AA}"'#'"${BB}"'#g' *.xml # apply to all *.xml files