Я пробую приведенный ниже код и надеюсь получить результат как 0 (т.е. $? -Eq 0
), но по какой-то причине это всегда терпит неудачу:
echo "INBOUND_PATH | / tmp "| grep -E '^ \ (INBOUND_PATH \) \ | \ (. * \) $';
echo $?
Я хотел создать обратную ссылку, потому что если бы формат строки был допустимым, я бы вырежьте каталог с помощью следующей команды:
g_inboundDir = grep -E 's / ^ \ (INBOUND_PATH \) \ | (. *) $ / \ 2';
Объединив пробел и собрав все ответы вместе, а также взглянув на справочную страницу grep (man grep
), мы видим два основных типа регулярных выражений :Basic Regex и Extended Regex.
Согласно man grep:
Basic vs Extended Regular Expressions
In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, +, {, \|, (,and ).
Другими словами, вы можете захватывать группы с помощью одного grep, используя escape-последовательность ()
, например grep \(....\)
, или если вы используете grep -E
или egrep
, вам не нужно экранировать круглые скобки:egrep '(....)'
К sed применяются те же правила. Простой sed понимает основные регулярные выражения, поэтому вам нужно экранировать для захвата групп:sed 's/\(....\)\(...\)/\2/'
или вы можете включить расширенную поддержку регулярных выражений в sed
с помощью переключателя -E
или -r
(в зависимости от реализации sed):sed -E 's/(...)(...)/\2/'
В результате все приведенные ниже команды действительны:
$ echo "INBOUND_PATH|/tmp" | grep '^\(INBOUND_PATH\)|\(.*\)$';echo $?
INBOUND_PATH|/tmp
0
$ echo "INBOUND_PATH|/tmp" | egrep '(INBOUND_PATH)\|(.*)$';echo $?
INBOUND_PATH|/tmp
0
$ echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)/\2/'
/tmp
$ echo "INBOUND_PATH|/tmp" | sed -E 's/(INBOUND_PATH)\|(.*)$/\2/'
/tmp
Обратите внимание на противоположную обработку специальных символов в разных регулярных выражениях.
Например, см. обработку символа трубы |
в приведенных выше командах:
В базовом регулярном выражении (BRE):
Вам не нужно экранировать символ трубы, чтобы соответствовать буквальному символу трубы.
Экранирующий символ вертикальной черты в BRE будет рассматриваться как оператор ИЛИ (, который случайно сработает в вашем случае ).
Аналогично, в BRE вам не нужно экранировать круглые скобки ( )
, чтобы соответствовать буквальным скобкам, но вам нужно экранировать круглые скобки, чтобы захватить группу.
В расширенном регулярном выражении (ERE):
Вам нужно экранировать символ трубы, чтобы сопоставляться буквально, поскольку по умолчанию в ERE символ трубы обрабатывается как оператор ИЛИ (, противоположная обработка по сравнению с BRE)
Точно так же в ERE вам нужно экранировать круглые скобки, чтобы соответствовать буквальному скобки (
, так как по умолчанию скобки в ERE используются для захвата групп.
Базовая проверка строки не должна быть такой уж сложной:echo "INBOUND_PATH|/tmp" | grep -q '^INBOUND_PATH|.*$'
Я полагаю, вы имели в виду, что второй должен быть sed, а не grep:g_inboundDir=$(echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)/\2/')
Обратите внимание на отсутствие -E. Я также исправил отсутствующий трейлинг /.
Вы добавляете -E, которое является расширенным регулярным выражением
-E, --extended-regexp Interpret PATTERN as an extended regular expression (ERE, see below).
И все еще избегая этого. В этом нет необходимости.
$ echo "INBOUND_PATH|/tmp" | grep -E '^(INBOUND_PATH)\|(\/.*)'; echo $?
INBOUND_PATH|/tmp
0
С другой стороны, вы можете использовать egrep с тем же эффектом (без -E ).