¿Cuál es la naturaleza del comando grep?

¿Cuál es la naturaleza del comando grep?

Quería recuperar todos los archivos .txt usando el carácter comodín '*'.
Probé este comando (y también sin las comillas " ") pero fallé.

ls | grep "*.txt"

Lo interesante es que si pongo otro carácter en el comando grep correspondiente a un archivo .txt en el directorio, funciona

>>ls | grep s*.txt
sample.txt

Sé que ls *.txtfuncionará, pero me sorprendió un poco la naturaleza del comando grep. ¿Alguien podría ayudarme por qué sucede esto?

¿Es por el hecho de que grep usa expresiones regulares? Por favor ayuda.

Respuesta1

En expresiones regulares, *significa "cualquier número del elemento anterior", no "cualquier número de caracteres", como ocurre en los patrones de shell. Y .significa "cualquier carácter". Entonces, para buscar "cualquier cosa, seguido de literal .txt", usarías .*\.txt. O simplemente \.txt, ya que normalmente las coincidencias de expresiones regulares buscan la coincidencia en cualquier parte de la línea. Por otra parte, \.txttambién coincidiría con un nombre de archivo como foo.txtgz, ya que .txtno tendría que estar al final. Deberías \.txt$bloquear el patrón hasta el final de la línea.

La expresión regular *.txtno tiene sentido, es un error o busca un asterisco literal, según la implementación y si está utilizando expresiones regulares básicas ( grep) o extendidas ( grep -E). Lo mejor es no usarlo.

Por otro lado, s*.txtbuscaría "cualquier número de letras s, luego cualquier carácter y luego literal txt". Esa es una expresión regular más válida, pero... todavía no coincide sample.txt.

En cambio, lo que sucede en su segundo comando es que, debido a que s*.txtno está entre comillas, el shell se expande s*.txtantes de grepverlo. Si el único archivo coincidente es sample.txt, entonces greplo buscará en la salida de ls. (Si hubiera varios nombres de archivos coincidentes, el primero se tomaría como patrón y el resto como nombres de archivos para grepleer. En ese caso, se ignoraría la entrada de la tubería).


Pero lstambién puede tomar una lista de archivos, así que si bien puedes usar

ls | grep '\.txt'

para obtener cualquier .txtarchivo, probablemente sería más fácil usar

ls *.txt 

en cambio.

Respuesta2

Esto se debe en parte a que greputiliza expresiones regulares (de hecho, eso es lo que resignifica el nombre; es la abreviatura degramoglobalrregularmiexpresiónpagimpresión).

El *comodín en las expresiones regulares es diferente del *comodín en el shell global.

En expresiones regulares, *significa "cero o más del objeto definido anteriormente". Sin embargo, .estambiénun comodín, que significa "un carácter".

En shell globs, *significa "cero o más caracteres". .no es un comodín en absoluto.

Cuando grepbusca el patrón "*.txt", busca cero o más de cualquier cosa, seguido exactamente de un carácter más, seguido de la cadena literal txt.

Cuando buscas grepel patrón "s*.txt"m you are looking for a literals , followed by zero or mores s, followed by any character, followed by the literal stringtxt`.

Es por eso que algo común que encontrarás en las expresiones regulares es .*, que significa "uno de cualquier carácter seguido de cero o más de cualquier carácter". Regexese para "literalmente cualquier combinación de caracteres distintos de cero caracteres".

Cuando le ls *.txtdice al shell "Busque cualquier nombre de archivo que coincida con el patrón global *.txt, enumerelos aquí y proporciónelos como argumentos para el lscomando.

Respuesta3

tenga en cuenta que grep está buscando el archivocontenidomientras que el primer argumento es el PATRÓN de búsqueda y otros argumentos se interpretan como ARCHIVOS para examinar

se vuelve más claro para usted cuando usa grep -H -obanderas o coloca grepun script dentro y lo ejecuta conbash -x script para ver cómo se expandieron los globos de shell antes de pasarlos como argumentos.

información relacionada