Каков наилучший способ преобразовать регулярное выражение в строку, которая может быть принята grep/sed в bash?
например, с учетом следующего регулярного выражения
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
bash это не нравится (поэтому это регулярное выражение нельзя использовать в grep)
$ echo "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"
-bash: syntax error near unexpected token `('
$ echo '(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])'
>
> ^C
Я предполагаю, что регулярное выражение нужно экранировать, но я не нашел хорошего инструмента, который мог бы сделать это за меня.
есть идеи, как я могу позволить grep использовать это регулярное выражение в bash?
Нужно цитировать целиком. В вашей строке есть " внутри, который рано заканчивает цитату и все портит. Избегайте кавычек внутри строки с помощью \", чтобы вся строка была заключена в кавычки.
@GeorgeVasiliou, как видите, я не могу заключать регулярное выражение в двойные\одинарные кавычки. поэтому я открываю кейс. интересно как это можно сделать :)
@Verpous Я знаю, что это нужно сбежать, это то, что я написал. Мне нужна команда\инструмент, который сделает это за меня без участия человека.
@Мистер. Откуда тогда приходит регулярное выражение и как вы собираетесь его использовать? Можете ли вы отредактировать свой пост с более конкретным примером вашего варианта использования, который иллюстрирует это?


С моей mquote (волшебная цитата):
$ mquote (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
>>> '(?:[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])'
Давайте объединим две полезные функции Bash, чтобы добиться этого.
Во-первых, вы можете полностью избежать необходимости экранировать строку, используя документ Here Doc с разделителем в кавычках (например, <<"separator"). Например, вы можете написать что-то вроде этого:
cat<<"EOF"
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
EOF
Во-вторых, обернув этот документ Here Doc в функцию, вы можете легко перенести его в переменную. С этого момента вы можете напрямую предоставить эту переменную для grep или sed.
Например:
function regex() {
cat<<"EOF"
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
EOF
}
echo "[email protected]" | grep -P $( regex )
Обратите внимание, что для вашего регулярного выражения требуется механизм регулярных выражений, совместимый с Perl (также известный как PCRE). Экранированные шестнадцатеричные последовательности внутри выражений классов символов (например, [\x70-\x7f]) не поддерживаются большинством других движков, что означает, что предыдущая последовательность будет соответствовать этим символам: \, x, 7, 0-\, x, 7, f).
возможно, он экранирует строку, но влияет на регулярное выражение, и поэтому регулярное выражение не фиксирует какой-либо адрес электронной почты.
Действительно. Я изменил объяснение того, как использовать регулярное выражение напрямую с egrep, без части printf '%q'.
Единственное, что вам нужно знать, это как заключить строку с одним кавычки, если строка содержит одинарные кавычки внутри. Позвольте мне упростить строку в качестве примера:
O'Reilly
Как вы знаете, обратная косая черта не работает, чтобы избежать одинарной кавычки внутри одинарных кавычек:
str='O\'Reilly' # wrong
Вместо этого вы можете сказать:
str='O'\''Reilly'
Это может показаться странным, но это просто конкатенация 'O', \' и 'Reilly'.
'O' ... single quoted string "O"
\' ... literal single quote
'Reilly' ... single quoted string "Reilly"
Затем вы можете назначить переменную своему регулярному выражению с помощью:
regex='(?:[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])'
# echo "$regex"
grep -P "$regex" <<< '[email protected]'
Обратите внимание, что две одинарные кавычки обрабатываются так же, как в приведенном выше примере.
Если я не ошибаюсь, вы пытаетесь использовать это регулярное выражение для захвата электронных писем. В этом аспекте вы можете использовать
grep -E -o "your regex here" file.txt- Также ознакомьтесь с этим постом: stackoverflow.com/questions/2898463/…