Ошибка sed: «недопустимая ссылка \ 1 в правой части команды` s '»

104

Я запускаю несколько команд подстановки в качестве ядра сценария раскраски для maven . Одна из sedкоманд использует регулярное выражение, которое работает в оболочке, как описано здесь . Текущую (не работающую) реализацию можно найти здесь .

Когда я включаю в скрипт один из вариантов команды, происходит другое поведение:

Вариант 1:

$ sed -re "s/([a-zA-Z0-9./\\ :-]+)/\1/g"

Адаптировано к сценарию:

-re "s/WARNING: ([a-zA-Z0-9./\\ :-]+)/${warn}WARNING: \1${c_end}/g" \

Ошибка: оболочка выводит такую ​​же информацию, как если бы я печатал $ sed. Странный!?


Вариант 2:

$ sed -e "s/\([a-zA-Z0-9./\\ :-]\+\)/\1/g"

Адаптировано к сценарию:

-e "s/WARNING: \([a-zA-Z0-9./\\ :-]\+\)/${warn}WARNING: \1${c_end}/g" \

Ошибка:

sed: -e выражение # 7, char 59: недопустимая ссылка \ 1 в правой части команды `s '

JJD
источник
10
В моем случае я объединил -i(редактировать в опции места) с -re, в результате чего -ire(так что -iбыло потребляя reфрагмент в качестве своего SUFFIXаргумента и , следовательно, режим расширенного регулярного выражения не быть включен); изменив его, чтобы -i -reустранить проблему.
Джанака Бандара
Также следует отметить, что одинарные 'и двойные кавычки "обрабатываются немного по-разному, особенно при интерпретации $vars. Например: sudo sh -c "sed -r -i 's/(^.+_supplicant.conf)/\1${MTXT}/' /etc/network/interfaces"работает, но: sudo sh -c 'sed -r -i "s/(^.+_supplicant.conf)/\1${MTXT}/" /etc/network/interfaces'нет.
not2qubit 02

Ответы:

53

Разве вам не нужно снимать, чтобы это работало? т.е. для варианта 2:

-r -e "s/WARNING: (\([a-zA-Z0-9./\\ :-]\+\))/${warn}WARNING: \1${c_end}/g" \

(Примечание: не проверено)

Без аргумента -r обратные ссылки (например, \ 1) работать не будут.

Дени де Бернарди
источник
42
Параметр -rsed, по-видимому, необходим для работы обратной ссылки. Например, sed -e 's/([[:digit:]])/is a digit/'работает, но sed -e 's/([[:digit:]])/\1 is a digit/выдает исходную ошибку без -rsed. ПРИМЕЧАНИЕ: первый вызов sed ищет литерал (<digit>)и не является группой захвата.
Эндрю Фаланга,
Комментарий под ответом на самом деле является ответом. Возможно, вы сможете отредактировать свой ответ, чтобы отразить его.
miroxlav 03
@AndrewFalanga, вы должны были опубликовать свой комментарий в качестве ответа
sanmai
2
Неважно, что моя ошибка заключалась в использовании -ireвместо использования -ri. Порядок имеет значение :-)
m3nda
55

Эта ошибка характерна для скобок, которые не экранированы. Убегите от них и попробуйте еще раз.


Например:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n(.)/\1/g

Перед каждой круглой скобкой следует использовать обратную косую черту:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g
e18r
источник
6
Внимание, если вы используете, -rвам не нужно избегать скобок.
qräbnö
13

Если параметр -r/ --regexp-extendedне указан, скобки захвата должны быть экранированы.

OrangeDog
источник
5

Вам нужно сбежать /после.

sed -e "s/\([a-zA-Z0-9.\/\\ :-]\+\)/\1/g"

Или, если вы не хотите беспокоиться о побеге, используйте |

sed -e "s|\([a-zA-Z0-9./\\ :-]\+\)|\1|g"

РЕДАКТИРОВАТЬ:

sed -e "s|WARNING: \([a-zA-Z0-9.-/\\ :]+\)|${warn}WARNING: \1${c_end}|g"
бездельник
источник
Звучит разумно. Но в контексте сценария это не работает.
JJD
Сожалею. Редактирование вызывает ошибку: sed: -e expression #7, char 58: Invalid range end. Ответ @Denis работает.
JJD
2
Хорошо, тогда +1 за ответ
@Denis