Evaluación de una cadena en script de shell

8

Estoy siguiendo esta guía de scripting de bash shell:

En la sección Comparaciones numéricas, cita un ejemplo:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

Lo que parece suceder arriba es que almacenamos una cadena de comandos en una variable bash y luego invocamos echo en la variable. Lo que parece suceder es que se evalúa la cadena y se ejecuta el comando wc y devuelve el recuento de líneas al terminal de control.

Ok, entonces lanzo mi terminal en Ubuntu 12.04 e intento algo similar:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

Espere un segundo, eso no evaluó la cadena y devolvió el recuento de líneas. Eso solo hizo eco de la cadena de regreso a la terminal. ¿Por qué obtuve resultados diferentes?

JohnMerlino
fuente
Tenga en cuenta que a num nunca se le asigna la cadena wc -l work.txt, sino que se le asigna el número 201.
ignis
Recurso relacionado: 3.5.4 Sustitución de comandos en el manual de referencia de Bash .
Eliah Kagan

Respuestas:

2

Necesitas usar backticks para evaluar la expresión.

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

Si desea ver solo "1" en la salida, use el comando

$ num=`cat sample.txt | wc -l`
$ echo $num
1

Y también funciona:

$ num=`wc -l < sample.txt`
$ echo $num
1

Para obtener información adicional, consulte Diferencias entre comillas dobles "", comillas simples '' y comillas inversas ´ ´ en la línea de comandos?

Danatela
fuente
¿Alguna idea de por qué obtengo '1 sample.txt' y no solo el número '1'?
JohnMerlino
Así es como funciona el wccomando. Tratar cat sample.txt | wc -l.
Danatela
wc -l muestra el número de líneas presentes en un archivo junto con su nombre de archivo.
Avinash Raj
5

Tenga en cuenta ese símbolo:

'

Una frase

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

y

``

Cita posterior

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

Por lo tanto, el Backquote devuelve el resultado del comando a Salida estándar. Es por eso que

`wc -l sample.txt`

devuelve resultados del comando, mientras

'wc -l sample.txt'

simplemente devuelva "wc -l sample.txt" como cadena habitual

Considere hacer esto como ejemplo:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

Y ahora repite las tres variables:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
c0rp
fuente
4

Si desea capturar la salida de un comando en una variable, debe usar los backticks ``o encerrar el comando en $():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

Tenga en cuenta que la cadena se evalúa realmente en el momento de la declaración de variable, no cuando la repite. El comando se ejecuta realmente dentro de las $()teclas de retroceso o y la salida de ese comando se guarda como el valor de la variable.

En general, siempre debe usar en $()lugar de backticks que están en desuso y solo por razones de compatibilidad y mucho más limitados. No puede, por ejemplo, anidar comandos dentro de backticks, pero puede hacerlo con $():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

Consulte este hilo en U&L para obtener más detalles sobre por qué ``debe evitarse.

terdon
fuente
1
Estoy de acuerdo guiones deberían preferir $( )a ` `. Pero como dice Wag, las comillas inversas anidan. echo $(date -d $(echo yesterday))se convierte echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))se convierte echo `echo \`date -d \\\`echo yesterday\\\`\``. Digo que esto no refuta su tesis, sino que la fortalece : las comillas internas escapadas hacen que la ` `sintaxis sea más poderosa de lo que a menudo se admite, pero el tratamiento especial \es extraño, sorprendente y difícil de razonar. Con $( )lo que ves es generalmente lo que obtienes.
Eliah Kagan