Por que minha expressão grep precisa usar $ 'string' para corresponder aos caracteres das guias?

6

Se você pegar este código:

echo -e '\t\t\tString' | grep '^[\t]*String'

o resultado está em branco porque não corresponde, mas isto:

echo -e '\t\t\tString' | grep $'^[\t]*String'

funciona. Eu juro que devo ter usado o código da primeira linha centenas de vezes em meus scripts e no terminal, sem nunca usar o caracter "$" assim, e sempre pareceu funcionar. Houve alguma mudança recente? Por que precisa do caractere "$"? Ou estou fazendo algo errado?

    
por Tal 16.11.2014 / 02:10

3 respostas

9

Citação ANSI-C

De acordo com o manual do Bash, isso se chama citações ANSI-C . O manual diz:

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.

Na prática, isso significa que '\t' não será expandido para um caractere de tabulação, mas $'\t' será. A saída deve ser equivalente a usar echo -e , mas pode ser usada em qualquer lugar em que você usasse uma string sem exigir substituição de comando .

Utilitários como o GNU sed executam sua própria expansão de caracteres de escape, mas o GNU grep não. O shell Bash, não o grep, expande os caracteres de escape em strings citadas em ANSI-C. Sem a cotação ANSI-C, a expressão regular que você publicou não contém caracteres de tabulação para corresponder à entrada.

    
por 16.11.2014 / 03:07
1

Você provavelmente deve perceber que não há um único tipo de expressões regulares. Há pelo menos basic regular expressions ou BRE (às vezes apenas RE ), extended regular expressions ou ERE e perl compatible regular expressions ou PCRE . Todas essas linguagens usam uma sintaxe ligeiramente diferente. As versões atuais de GNU grep suportam todos os três e os BRE são padrão. Para ERE , você precisa usar a opção -E e a opção PCRE -P . Seu exemplo funcionará somente com -P , já que com o RE básico e estendido a barra invertida perde o significado e [\t] corresponde à barra invertida ou ao caractere t. Você provavelmente estava usando esse padrão em alguma outra linguagem que suporta PCRE por padrão, o que faz sentido, já que eles são a versão mais poderosa. Ou talvez você tenha alias grep='grep -P' em algum lugar.

    
por 16.11.2014 / 03:36
0

A primeira linha funciona se você deixar de fora o ^ . Talvez funcionou, mas não funcionou da maneira que você imaginou? Eu duvido que o comportamento do grep tenha mudado em um ponto tão importante.

echo não traduz sequências de escape por padrão. Você precisa do -e para isso. Semelhante ao shell. Você precisa de $'...' para fazer com que o shell use sequências de escape.

    
por 16.11.2014 / 03:08