Проблема довольно сложная: вам нужно заменить все вхождения текста из нескольких символов в блоках текста между одинаковыми разделителями из нескольких символов.
Самый простой и безопасный способ решения задачи -используя Perl:
perl -i -pe 's/(@@)(.*?)(@@)/$end_delim=$3; "$1" . $2=~s|KEY-|VALUE-|gr . "$end_delim"/ge' file
См. онлайн-демонстрацию .
Шаблон (@@)(.*?)(@@)
будет сопоставлять строки между двумя смежными подстроками @@
, захватывающими начальный разделитель в группу1, конечный разделитель в группе 3 и весь текст между ними в группе 2. Поскольку подстановка регулярного выражения переустанавливает все заполнители, временная переменная используется для сохранения значения конечного разделителя ($end_delim=$3
), затем "$1" . $2=~s|KEY-|VALUE-|gr . "$end_delim"
заменяет совпадение значением в группе 1 первого совпадения (первым @@
), затем значение группы 2 со всеми KEY-
, заменяемыми на VALUE-
, и затем конечным разделителем.
Если между матчами в одной строке нет KEY-
с , вы можете использовать ветку с sed
, заключив свою команду в :A
и tA
:
sed -i ':A; s/\(@@[^@]*\)KEY-\([^@]*@@\)/\1VALUE-\2/g; tA' file
Обратите внимание, что вы пропустили первый заполнитель в \VALUE-\2
, это должно быть \1VALUE-\2
.
См. онлайн-демонстрацию :
s="some KEY- text
some text @@some-text-KEY-some-other-text@@
text again @@some-text-KEY-some-other-text@@ @@some-text-KEY-some-other-text@@
again @@some-text-KEY-some-other-text-KEY-text@@
some text with KEY @@KEY-some-text@@
blabla @@KEY@@"
sed ':A; s/\(@@[^@]*\)KEY-\([^@]*@@\)/\1VALUE-\2/g; tA' <<< "$s"
Вывод:
some KEY- text
some text @@some-text-VALUE-some-other-text@@
text again @@some-text-VALUE-some-other-text@@ @@some-text-VALUE-some-other-text@@
again @@some-text-VALUE-some-other-text-VALUE-text@@
some text with KEY @@VALUE-some-text@@
blabla @@KEY@@
Подробнее :
sed
позволяет использовать петли и ветви .:A
в приведенном выше коде - это метка , особый маркер местоположения, на который можно «прыгнуть», используя соответствующий оператор.t
используется для создания ветви, эта команда переходит на метку, только если предыдущая команда замены была успешной".Таким образом, как только шаблон сопоставлен и замена произошла, sed
возвращается туда, где он был, и повторяет попытку сопоставления.Если это не удалось, sed
продолжает поиск совпадений в строке.Таким образом, tA
означает вернуться к месту, отмеченному A
, если была успешная операция поиска и замены .