
Si tomas este código:
echo -e '\t\t\tString' | grep '^[\t]*String'
el resultado está en blanco porque no coincide, pero esto:
echo -e '\t\t\tString' | grep $'^[\t]*String'
obras. Juro que debí haber usado el código de la primera línea cientos de veces en mis scripts y en la terminal, sin usar nunca el carácter "$" de esa manera, y siempre pareció funcionar. ¿Ha habido algún cambio reciente? ¿Por qué necesita el carácter "$"? ¿O estoy haciendo algo mal?
Respuesta1
Cotización ANSI-C
Según el manual de Bash, esto se llamacotización ANSI-C. El manual dice:
palabras de la forma$'cadena'son tratados de manera especial. La palabra se expande a una cadena, con caracteres de escape con barra invertida reemplazados según lo especificado por el estándar ANSI C.
En la práctica, esto significa que '\t'
no se expandirá a un carácter de tabulación, pero $'\t'
lo hará. La salida debería ser equivalente a usar echo -e
, pero se puede usar en cualquier lugar donde se use una cadena sin necesidad desustitución de comando.
Utilidades como GNU sed realizan su propia expansión de caracteres de escape, pero GNU grep no. El shell Bash, no grep, expande los caracteres de escape dentro de cadenas entre comillas ANSI-C. Sin las comillas ANSI-C, la expresión regular que publicó no contiene caracteres de tabulación que coincidan con la entrada.
Respuesta2
Probablemente deberías darte cuenta de que no existe un único tipo de expresiones regulares. Hay al menos basic regular expressions
o BRE
(a veces solo RE
), extended regular expressions
o ERE
y perl compatible regular expressions
o PCRE
. Todos esos idiomas utilizan una sintaxis ligeramente diferente. Las versiones actuales son GNU grep
compatibles con los tres y BRE
son predeterminadas. Para ERE
necesita usar -E
la opción y la PCRE
-P
opción. Su ejemplo funcionará solo -P
con RE básico y extendido, la barra invertida pierde su significado y [\t]
coincide con la barra invertida o el carácter t. Probablemente estabas usando ese patrón en algún otro idioma que sea compatible PCRE
de forma predeterminada, lo cual tiene sentido ya que es la versión más potente. O tal vez lo tenías alias grep='grep -P'
en alguna parte.
Respuesta3
La primera línea funciona si omites el ^
. ¿Quizás funcionó pero no funcionó como suponías? Dudo que grep
el comportamiento haya cambiado en un punto tan importante.
echo
no traduce secuencias de escape de forma predeterminada. Necesitas el -e
para eso. Lo mismo ocurre con el caparazón. Necesitas $'...'
hacer que el shell use secuencias de escape.