Вопрос про многострочную замену в sed довольно распространён, но, увы,
SLEDopit ответил на него неверно.
sciko
$ cat test.txt
if (!session_is_registered("none")) exit;
if (!session_is_registered("auth"))
{
exit;
}
$ sed -e '/if.*session_is_registered/{N;N;N;s/if (!session_is_registered("auth"))\s*\n\s*{\s*\n\s*exit;\s*\n\s*}/if(!isset($_SESSION["auth"])) exit;/;}' test.txt
if (!session_is_registered("none")) exit;
if (!session_is_registered("auth"))
{
exit;
}
$ WTF?
В чём же причина? А причина одна --
безблагодатность неверный алгоритм.
Как работает вышеописанный скрипт для sed? Сперва ищется строка совпадающая с регэкспом "if.*session_is_registered". Если она найдена, то выполняется блок команд (те, что между фигурными скобками).
Сам блок команд же очень прост: в рабочий буфер sed считывается ещё 3 строки ("N;N;N;"), после чего происходит попытка замены через операцию s///.
Однако проблема в том, что, если регэксп "if.*session_is_registered" совпадает с некой строкой, то ещё 3 строки считываются в любом случае, даже если там не произошло замены. Если же на эти 3 строки попадётся нужный для замены участок, то он будет пропущен.
Так какой же вариант правильный? Увы и ах, он очень сложен. Поэтому я приведу просто работоспособный:
Код: Выделить всё
for file in *mask ; do sed -i.bak ':a;N;s/if (!session_is_registered("auth"))\s*\n\s*{\s*\n\s*exit;\s*\n\s*}/if(!isset($_SESSION["auth"])) exit;/g;ta' $file ; done
Как это работает?
Создаётся метка "a" (команда ":a;"). Далее считывается очередная строка (команда ":N;") и производится попытка замены. Если попытка замены -- неудачная, то происходит переход на метку "a" (команда "ta;").
Почему этот скрипт -- неверный? Потому что, если в файле менять нечего, то в рабочий буфер sed будет считан весь файл, что не есть хорошо.