Por que minha expressão grep precisa usar $'string' para corresponder aos caracteres de tabulação?

Por que minha expressão grep precisa usar $'string' para corresponder aos caracteres de tabulação?

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. Juro que devo ter usado o código da primeira linha uma centena de vezes em meus scripts e no terminal, sem nunca usar o caractere "$" assim, e sempre pareceu funcionar. Houve alguma mudança recente? Por que precisa do caractere "$"? Ou estou fazendo algo errado?

Responder1

Citação ANSI-C

De acordo com o manual do Bash, isso é chamadoCitação ANSI-C. O manual diz:

Palavras do formulário$'string'são tratados especialmente. A palavra se expande para string, com caracteres de escape de barra invertida substituídos conforme especificado pelo padrão ANSI C.

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 using echo -e, mas pode ser usada em qualquer lugar onde você usaria uma string sem a necessidadesubstituição de comando.

Utilitários como o GNU sed realizam sua própria expansão de caracteres de escape, mas o GNU grep não. O shell Bash, e não o grep, expande caracteres de escape dentro de strings entre aspas ANSI-C. Sem as aspas ANSI-C, a expressão regular que você postou não contém caracteres de tabulação para corresponder à entrada.

Responder2

Você provavelmente deve perceber que não existe um único tipo de expressões regulares. Existem pelo menos basic regular expressionsou BRE(às vezes apenas RE), extended regular expressionsou EREe perl compatible regular expressionsou PCRE. Todas essas linguagens usam sintaxe ligeiramente diferente. As versões atuais GNU grepsuportam todos os três e BREsão padrão. Para EREvocê precisa usar -Eopção e para PCRE -Popção. Seu exemplo funcionará apenas -Pcom RE básico e estendido, a barra invertida perde seu significado e [\t]corresponde à barra invertida ou ao caractere t. Você provavelmente estava usando esse padrão em alguma outra linguagem que suporta PCREpor padrão, o que faz sentido já que é a versão mais poderosa. Ou talvez você tivesse alias grep='grep -P'algum lugar.

Responder3

A primeira linha funciona se você deixar de fora o ^. Talvez tenha funcionado, mas não funcionou do jeito que você imaginou? Duvido que grepo comportamento tenha mudado num ponto tão importante.

echonão traduz sequências de escape por padrão. Você precisa do -epara isso. Semelhante com a casca. Você precisa $'...'fazer o shell usar sequências de escape.

informação relacionada