¿Cuál es la diferencia entre grep apple file y grep "apple" file?

22

¿Cuál es la diferencia entre grep apple filey grep "apple" file? ¿Qué hace poner las comillas? Ambos parecen funcionar y hacen exactamente lo mismo (mostrar la misma línea).

John Stacen
fuente

Respuestas:

45

Las comillas tienen un efecto sobre los caracteres que su shell considera especiales y tienen un significado sintáctico. En su ejemplo, esto no hace la diferencia porque appleno contiene tales caracteres.

Pero considere otro ejemplo: grep apple tree filebuscará la palabra appleen los archivos treey file, mientras grep "apple tree" fileque buscará la palabra apple treeen el archivo file. Las comillas le dicen a bash, que la palabra espacio "apple tree"no inicia un nuevo parámetro sino que será parte del parámetro actual. grep apple\ tree fileproduciría el mismo resultado, porque \le dice a bash que ignore el significado especial del siguiente carácter y lo trate literalmente.

David Foerster
fuente
2
Esto también es visible con comodines. Si lo hace grep a*b equations.txt, buscará a*b, a menos que haya un archivo en el directorio actual que comience con a y termine en b, en cuyo caso (porque (ba) sh expandirá los nombres de archivo en la línea de comando) se llamará a grep con completar diferentes parámetros, lo que resulta en diferentes resultados. Esto suele ser más un problema con find, ya que un comando como find . -name *.txtdará lugar a un comportamiento inesperado, si hay un archivo txt en el directorio actual. Es mejor usar comillas en este caso.
SztupY
44
Otro punto importante es la diferencia entre comillas dobles ( ") y comillas simples ( '). Las comillas simples impiden la interpretación de ciertos caracteres como $, mientras que las comillas dobles permiten la interpretación. Por ejemplo grep '${USER}', buscará el texto ${USER}, mientras grep "${USER}"que buscará el texto que USERcontiene la variable (por ejemplo johnstacen).
Paddy Landau
23

Las comillas dobles permiten la evaluación, las comillas simples impiden la evaluación, ninguna comilla permite la expansión de comodines, cuando se usa en la línea de comandos. Como ejemplos artificiales:

[user@work test]$ ls .
A.txt B.txt C.txt D.cpp

# The following is the same as writing echo 'A.txt B.txt C.txt D.cpp'
[user@work test]$ echo *
A.txt B.txt C.txt D.cpp

[user@work test]$ echo "*"
*

[user@work test]$ echo '*'
*

# The following is the same as writing echo 'A.txt B.txt C.txt'
[user@work test]$ echo *.txt
A.txt B.txt C.txt

[user@work test]$ echo "*.txt"
*.txt

[user@work test]$ echo '*.txt'
*.txt

[user@work test]$ myname=is Fred; echo $myname
bash: Fred: command not found

[user@work test]$ myname=is\ Fred; echo $myname
is Fred

[user@work test]$ myname="is Fred"; echo $myname
is Fred

[user@work test]$ myname='is Fred'; echo $myname
is Fred

Comprender la forma en que funcionan las citas es fundamental para comprender Bash. Por ejemplo:

# for will operate on each file name separately (like an array), looping 3 times.
[user@work test]$ for f in $(echo *txt); do echo "$f"; done;
A.txt
B.txt
C.txt

# for will see only the string, 'A.txt B.txt C.txt' and loop just once.
[user@work test]$ for f in "$(echo *txt)"; do echo "$f"; done;
A.txt B.txt C.txt

# this just returns the string - it can't be evaluated in single quotes.
[user@work test]$ for f in '$(echo *txt)'; do echo "$f"; done;
$(echo *txt)

Puede usar comillas simples para pasar un comando a través de una variable. Las comillas simples evitarán la evaluación. Se evaluarán las comillas dobles.

# This returns three distinct elements, like an array.
[user@work test]$ echo='echo *.txt'; echo $($echo)
A.txt B.txt C.txt

# This returns what looks like three elements, but it is actually a single string.
[user@work test]$ echo='echo *.txt'; echo "$($echo)"
A.txt B.txt C.txt

# This cannot be evaluated, so it returns whatever is between quotes, literally.
[user@work test]$ echo='echo *.txt'; echo '$($echo)'
$($echo)

Puede usar comillas simples dentro de comillas dobles y puede usar comillas dobles dentro de comillas dobles, pero las comillas dobles dentro de comillas simples no se deben hacer (sin escapar de ellas) no se evaluarán, se interpretarán literalmente. Las comillas simples dentro de comillas simples no deben hacerse (sin escapar de ellas).

Tendrá que obtener una comprensión profunda de las citas para usar Bash de manera efectiva. ¡Muy importante!

Como regla general, no uso comillas si quiero que Bash expanda algo en elementos (como una matriz), uso comillas simples para cadenas literales que no se deben alterar, y hago un uso liberal de comillas dobles para variables que probablemente devuelvan cualquier tipo de cadena. Esto es para garantizar que se conservarán los espacios y los caracteres especiales.

AsymLabs
fuente
¿Cómo usarías comillas dobles dentro de comillas dobles? ¿Es eso un error tipográfico? ¿Y por qué debería escapar de las comillas dobles entre comillas simples? ¿Supongo que mezclaron las oraciones quizás?
Byte Commander
@ByteCommander Sí, el concepto de comillas dobles colocadas dentro de comillas dobles se usa con bastante frecuencia; consulte esta publicación para ver un ejemplo de trabajo destacado. Por lo general, se hace para proteger cadenas que contienen espacios, a menudo con respecto a las cadenas de ruta. Las comillas dobles se pueden usar dentro de comillas simples con o sin escape, pero se interpretarán literalmente, es decir, no conducirán a una evaluación. Aclararé este punto en la publicación.
AsymLabs