Linux grep com pergunta de expressão regular

0

Estou tentando o código abaixo e esperando obter o resultado como 0 (ou seja, $? -eq 0 ), mas, por algum motivo, ele sempre falha:

echo "INBOUND_PATH|/tmp" | grep -E '^\(INBOUND_PATH\)\|\(.*\)$';

echo $?

O motivo pelo qual eu queria criar uma referência de retorno é porque, se o formato de string fosse válido, eu cortaria o diretório com o seguinte comando:

g_inboundDir=grep -E 's/^\(INBOUND_PATH\)\|(.*)$/';

    
por AlluSingh 08.07.2017 / 18:26

3 respostas

1

Colocando a lacuna e todas as respostas juntas, e também observando a página man do grep ( man grep ), temos dois tipos principais de expressões regulares: Regex Básico e Regex Estendido.

De acordo com o homem grep:

Basic vs Extended Regular Expressions
In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, +, {, \|, (,and ).

Em outras palavras, você pode capturar grupos com um único grep usando escape () como grep \(....\) ou se você usa grep -E ou egrep você não precisa escapar parênteses: egrep '(....)'

Mesmas regras se aplicam ao sed. Um simples sed entende expressões regulares básicas, portanto, é necessário escapar para capturar grupos: sed 's/\(....\)\(...\)//' ou você pode ativar o suporte de regex estendido na opção sed com -E ou -r (dependendo da implementação do sed): sed -E 's/(...)(...)//'

Como resultado, todos os comandos abaixo são válidos:

$ 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\)|\(.*$\)//'
/tmp

$ echo "INBOUND_PATH|/tmp" | sed -E 's/(INBOUND_PATH)\|(.*)$//'
/tmp

Preste atenção ao manuseio de símbolos especiais em diferentes Regexes.

Por exemplo, veja o tratamento do símbolo pipe | nos comandos acima:
Na regex básica (BRE):
Você não precisa escapar símbolo pipe para coincidir com um símbolo de pipe literal.
Escapando símbolo de tubo no BRE, será considerado como um operador OR (que acidentalmente funcionará no seu caso).

Similarilly, no BRE você não precisa escapar do parêntese ( ) para corresponder a um parêntese literal, mas você precisa escapar dos parênteses para capturar um grupo.

Em regex estendido (ERE):
Você precisa escapar do símbolo do pipe para ser correspondido literalmente, já que por padrão no símbolo ERE pipe é tratado como operador OR (manipulação oposta comparada ao BRE)

Similarilly em ERE você precisa escapar dos parênteses para combinar com um literall parêntese ( , já que, por padrão, parênteses em ERE são usados para capturar grupos.

    
por 09.07.2017 / 01:30
0

A verificação básica da string não precisa ser tão complicada:
echo "INBOUND_PATH|/tmp" | grep -q '^INBOUND_PATH|.*$'

Suponho que você quis dizer que o segundo seja sed, não grep:
g_inboundDir=$(echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)//')

Observe a falta de -E. Eu também consertei o trailing ausente /.

    
por 08.07.2017 / 20:26
0

Você está adicionando -E, que é uma expresão regular estendida

-E, --extended-regexp Interpret PATTERN as an extended regular expression (ERE, see below).

E ainda escapando disso. Não é necessário.

$ echo "INBOUND_PATH|/tmp" | grep -E '^(INBOUND_PATH)\|(\/.*)'; echo $?
INBOUND_PATH|/tmp
0

Por outro lado, você pode usar egrep com o mesmo efeito (sem -E).

    
por 08.07.2017 / 21:26