Как сохранить сложное регулярное выражение для многократного повторного использования в sed?


12

При использовании sedя часто создаю довольно сложные и сложные регулярные выражения, которые мне нужно дважды сопоставить в файле. Есть ли способ для меня, чтобы сохранить это регулярное выражение и просто сослаться на него дважды?

Может быть, что-то похожее на это?

sed ' complicated_regex=/^(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+$/
s/complicated_regex:complicated_regex/simple-output/
' my_file

Обновление: ответ представил решение использования переменной bash. Это не работает Учитывая test.txt.

#test.txt
foo bar
bar foo

И сценарий

#!/bin/bash

VALUE='foo \([a-z]\+\)'

sed 's/"${VALUE}"/foo happy \1/' test.txt

Это должно произвести вывод

foo happy bar
bar foo

Но вместо этого я получаю ошибку

sed: -e expression #1, char 24: invalid reference \1 on `s' command's RHS

Если вы используете Perl, вы можете ссылаться на предыдущие части выражения в выражении:perl -pe 's/^(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+:\1$/simple_output/' my_file
glenn jackman

1
Когда вы найдете что-то слишком сложное для sed, не стесняйтесь использовать awk или perl.
Жиль "ТАК - перестань быть злым"

2
@Cory: Ваш пример работает нормально, если вы правильно поняли его синтаксис. У вас есть «переменная $», все еще заключенная в «одинарные кавычки», которая скрывает ее от ожидаемого расширения оболочки ... так и должно бытьsed 's/'"${VALUE}"'/foo happy \1/' test.txt
Peter.O

Ответы:


7

Вы можете использовать переменные оболочки:

complicated_regex='(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+'
sed s/^"$complicated_regex":"$complicated_regex"\$/'simple-output'/ my_file

Я не уверен в том, что вы имели в виду $i, но вам может потребоваться поместить это в одинарные кавычки:

complicated_regex='(([a-f0-9]{32})+([a-zA-Z0-9=]{{'"$i"'}})?)+'

Конечно, это работает, только если sedкоманда вызывается из оболочки, но существует аналогичное решение почти со всеми языками программирования. (И я не думаю, что можно использовать переменные внутри sed.)
Стефан Гименес

Хмм. Пытаясь это, обратные ссылки кажутся сломанными. s/$complicated_regex/\1/выдает ошибку, говоря, что это недопустимая ссылка.
Кори Кляйн

Ах, может быть, моя вина, я привык к замене переменных zsh. Смотрите обновленный ответ.
Стефан Гименес

Вам придется удалить якоря из переменной и поместить их в сценарий sed:sed "s/^${complicated_regex}:${complicated_regex}\$/simple-output/" my_file
glenn jackman

Duh! Да, я забыл проверить, что мне предоставили действительное объединение регулярных выражений :-)
Стефан Гименес

0

Самый простой способ добавить значение переменной оболочки sedи не беспокоиться о том, что вам потребуется изменить экранирование обратной косой черты для остальной части вашего sedсценария, - это поместить все в одинарные кавычки, кроме переменной, и поместить их в двойные кавычки.

Все следующие примеры кода предполагают: VALUE='foo \([a-z]\+\)'

Следующий неработающий код завершается ошибкой, потому что переменная VALUEне раскрыта:

sed 's/"${VALUE}"/foo happy \1/' test.txt

Следующий неработающий код завершается ошибкой, потому что обратная косая черта \1включается оболочкой (потому что она в двойных кавычках, а не в одинарных кавычках) до того, sedкак ее увидит:

sed "s/${VALUE}/foo happy \1/" test.txt

Следующий код работает как положено:

sed 's/'"${VALUE}"'/foo happy \1/' test.txt

Также работает следующий код:

sed "s/${VALUE}/foo happy \\1/" test.txt

Так же и следующее:

sed s/"${VALUE}"/foo\ happy\ \\1/ test.txt

Но почему сложно? Одинарные кавычки вокруг sedскрипта делают все намного понятнее, особенно для не-shell-скриптов-гуру, читающих ваш код. Мой любимый способ, опять же, выпадать из одинарных кавычек в двойные кавычки только для раскрытия переменной и переходить сразу к одинарным кавычкам:

sed 's/'"${VALUE}"'/foo happy \1/' test.txt
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.