
Tengo un archivo con el siguiente contenido:
sh-4.2$ cat file1
example of multiple
pattern
this is an
example of multipole
sorry multiple
pattern matching
using grep
so the example is the
file itself
-example
-multiple
-bye
tata
!
Mientras busca "-example" en el archivo anterior, el comando grep no proporciona el resultado deseado. Sé que si el patrón contiene '-' entonces se debe usar la opción -e:
En el primer ejemplo utilicé-ejemplodirectamente sin comillas:
sh-4.2$ grep -example file1
example of multiple
example of multipole
so the example is the
-example
-ejemplocon comillas simples:
sh-4.2$ grep '-example' file1
example of multiple
example of multipole
so the example is the
-example
-ejemplocon comillas dobles y caracteres de escape
sh-4.2$ grep "\-example" file1
-example
sh-4.2$
Respuesta1
Bueno, sabes que el patrón de búsqueda contiene un '-', y sabes que cuando el patrón de búsqueda contiene un '-' necesitas usar la -e
bandera. Como no está utilizando la -e
bandera, el shell interpreta su "patrón" como un argumento (y un parámetro). Puedes ver eso con:
$ grep "-foo" file1
grep: oo: No such file or directory
Por extensión, su código grep "-example" file1
le dice al Shell que desea ejecutar grep
con el -e
argumento y un parámetro "ejemplo".
Este es el mismo problema con el que nos encontramos cuando intentamos algo así rm -my-silly-file-name
: no funcionará y necesitamos usar algo así rm ./-my-silly-file-name
en su lugar. Otra solución sería rm -- -my-silly-file-name
. Podemos usar ese modismo aquí:
$ grep -- "-example" < file1
-example
El "--" le dice al shell que todo lo que sigue esnoun argumento.
Alternativamente, puedes simplemente escapar del "-" con un "\", como has visto:
grep "\-example" file1
Este artículo detalla algunos detalles sobre las citas.: la parte relevante esLos parámetros y comandos entre comillas que el shell debe interpretar están entre comillas dobles.Cuando utiliza comillas dobles, el contenido es interpretado por el shell.
Respuesta2
Usted "sabe si el patrón [comienza con] '-' entonces se debe usar la opción -e", pero no lo está usando cuando debería. grep -e -example file1
le dará el resultado esperado.
Esto es lo que realmente se ejecuta en cada uno de sus ejemplos:
grep -example file1
=>grep -e xample file1
(-e es necesario)grep '-example' file1
=>grep -e xample file1
(-e es necesario)grep "\-example" file1
=>grep \-example file1
(-e no es necesario)
Respuesta3
-
Se toma como opción un argumento que comienza con .
En los dos primeros casos, el primer argumento pasado grep
es -example
, que grep
se entiende como -e xample
( xample
argumento de la -e
opción, así que busque xample
).
En el tercer caso \-example
se pasa a grep
. Como no comienza con -
, no se toma como opción. En su lugar, se toma como una expresión regular. Sin embargo, el comportamiento \-
no está especificado según POSIX, por lo que no tiene garantía de con qué coincide. Con la mayoría de grep
las implementaciones, \-
coincidirá con a -
, sin embargo, puede imaginar grep
implementaciones donde \-
puede haber un operador especial (consulte, por ejemplo, GNU, grep
donde \+
hay un operador especial y no coincide con un literal +
).
Si no desea -example
que se le tome como opción, necesita:
grep -- -example file
. El--
marca el final de las opciones. Todo lo que sigue no es una opción (por lo que el primer argumento es el patrón a buscar y el resto la lista de archivos a buscar).grep -e -example file
. Aquí,-example
se toma como argumento de la-e
opción.
Ese es el tipo de razón por la que deberías acostumbrarte a escribir:
grep -e "$pattern" file
O
grep -- "$pattern" file
Si no puede garantizarlo, $pattern
no comenzará con -
.
Tenga en cuenta que aquí también puede escribirlo:
grep '[-]example' file
aunque verExpresión entre corchetes (sin rangos) que coincide con un carácter inesperado en bashsobre posibles complicaciones con ese enfoque.