
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 expressions
ou BRE
(às vezes apenas RE
), extended regular expressions
ou ERE
e perl compatible regular expressions
ou PCRE
. Todas essas linguagens usam sintaxe ligeiramente diferente. As versões atuais GNU grep
suportam todos os três e BRE
são padrão. Para ERE
você precisa usar -E
opção e para PCRE
-P
opção. Seu exemplo funcionará apenas -P
com 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 PCRE
por 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 grep
o comportamento tenha mudado num ponto tão importante.
echo
não traduz sequências de escape por padrão. Você precisa do -e
para isso. Semelhante com a casca. Você precisa $'...'
fazer o shell usar sequências de escape.