Странность регулярного выражения 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"

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

См. здесь, чтобы узнать разницу между базовыми регулярными выражениями (BRE) и расширенными регулярными выражениями (ERE).

potong 31.08.2024 01:37

Кроме того: -r является аргументом в пользу включения ERE только в старых версиях GNU sed. Современные версии GNU и BSD sed используют -E для включения ERE, как и grep.

Ed Morton 31.08.2024 14:32

@EdMorton -E также вошёл в последний стандарт - pubs.opengroup.org/onlinepubs/9799919799/utilities/sed.html

jhnc 01.09.2024 01:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
3
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 будет воспринимать { и } как буквальные символы, что позволит вам выполнить замену так, как предполагалось.

у "{" есть 2 обратные косые черты? //{ Я определенно что-то пропустил. Должно быть, это что-то типа bash.

Floyd Brown 30.08.2024 20:36

@FloydBrown это мера предосторожности, позволяющая гарантировать, что bash передает команде буквальную обратную косую черту. В данном случае это не обязательно, но позволяет избежать необходимости помнить, когда это необходимо. bash обрабатывает доллар, обратную косую черту, обратную косую черту и иногда восклицательный знак как метасимволы, заключенные в двойные кавычки. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or <newline>.. POSIX sh делает то же самое: pubs.opengroup.org/onlinepubs/9699919799/utilities/…

jhnc 30.08.2024 20:45

для 2. строка для sed должна быть "s/: = {MMC...", поскольку \{ включит обработку как диапазон, что здесь нежелательно

jhnc 30.08.2024 20:55

Чтобы расширить то, что говорит @jhnc, в этом ответе все наоборот: -E/-r не требует экранирования для {, [, + и т. д.; sed без параметров делает. В этом разница между «базовыми» и «расширенными» регулярными выражениями POSIX. В GNU sed они различаются только тем, что нужно экранировать, а что нет.

Benjamin W. 31.08.2024 00:04
Ответ принят как подходящий

Ваша команда 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'

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

Другие вопросы по теме