¿Por qué mi expresión grep necesita usar $'string' para coincidir con los caracteres de tabulación?

¿Por qué mi expresión grep necesita usar $'string' para coincidir con los caracteres de tabulación?

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 expressionso BRE(a veces solo RE), extended regular expressionso EREy perl compatible regular expressionso PCRE. Todos esos idiomas utilizan una sintaxis ligeramente diferente. Las versiones actuales son GNU grepcompatibles con los tres y BREson predeterminadas. Para EREnecesita usar -Ela opción y la PCRE -Popción. Su ejemplo funcionará solo -Pcon 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 PCREde 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 grepel comportamiento haya cambiado en un punto tan importante.

echono traduce secuencias de escape de forma predeterminada. Necesitas el -epara eso. Lo mismo ocurre con el caparazón. Necesitas $'...'hacer que el shell use secuencias de escape.

información relacionada