Странность регулярного выражения sed

пытаясь заменить строку в sed встроенными { и $ и -E или -r, { для меня проблематичен.

согласно документации и многим примерам, которые я прочитал, мне нужно будет избегать только { и $, если тестировать их. Я сократил простейший случай (ниже).

Наверное я чего-то не понимаю

Я могу использовать свой обходной путь, но это должно работать с \{ ?

Данная строка:

: "${TARGET_PART:=${MMC_PART2}}"

и part=5

Я хочу заменить ${MMC_PART2}} на ${MMC_PART5}}

Не работает следующее:

echo ': "${TARGET_PART:=${MMC_PART2}}"'|  sed -r "s/:=\{(MMC_PART).}}/\1$part}}/g"

но следующее работает - (заменено "{" на ".")

echo ': "${TARGET_PART:=${MMC_PART2}}"'|  sed -r "s/:=.(MMC_PART).}}/\1$part}}/g"

Что мне не хватает?


4
69
2

Ответы:

Проблема, с которой вы столкнулись, связана с тем, как sed интерпретирует специальные символы, такие как { и }, в расширенных регулярных выражениях (с -E или -r). В sed { и } используются для интервальных выражений, и их необходимо экранировать, если вы хотите сопоставить их буквально, даже если вы не используете их в контексте повторения шаблона.

В вашей первой команде sed { в шаблоне s/: = {(MMC_PART).}}/ интерпретируется как начало интервального выражения, а не как буквальная фигурная скобка.

Вот правильный способ справиться с этим:

1. Замените { и } обратной косой чертой, чтобы они соответствовали буквально.

Итак, ваша команда sed должна выглядеть так:

echo ': "${TARGET_PART:=${MMC_PART2}}"' | sed -r "s/:=\\{(MMC_PART)\\}\\}/:\\{\1$part\\}\\}/g"

Альтернативно, если вы хотите избежать побега:

2. Используйте sed без -E или -r и используйте обратную косую черту для всех специальных символов:

echo ': "${TARGET_PART:=${MMC_PART2}}"' | sed "s/:=\{MMC_PART2\}/:=\{MMC_PART$part\}/g"

Это гарантирует, что sed будет воспринимать { и } как буквальные символы, что позволит вам выполнить замену так, как предполагалось.


Решено

Ваша команда sed синтаксически правильна, но не учитывает $ в:

: "${TARGET_PART:=${MMC_PART2}}"

Замена тоже кажется неправильной.

Первая команда должна быть:

part=5
echo ': "${TARGET_PART:=${MMC_PART2}}"'|  sed -r "s/(:=\\\$\{MMC_PART).(}})/\1$part\2/g"

для вывода:

: "${TARGET_PART:=${MMC_PART5}}"

Обратите внимание, что внутри двойных кавычек обратную косую черту и доллар следует экранировать, чтобы избежать изменений в оболочке. Внутри одинарных кавычек это не обязательно:

echo ': "${TARGET_PART:=${MMC_PART2}}"'|  sed -r 's/(:=\$\{MMC_PART).(}})/\1'"$part"'\2/g'

Ваша вторая команда не выполняет для меня никакой замены. Возможно, это было неправильно записано в вопросе.