Script Bash: contenido variable como un comando para ejecutar

159

Tengo un script de Perl que me da una lista definida de números aleatorios que corresponden a las líneas de un archivo. A continuación, quiero extraer esas líneas del archivo usando sed.

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var=$(perl test.pl test2 $count)

La variable vardevuelve una salida como: cat last_queries.txt | sed -n '12p;500p;700p'. El problema es que no puedo ejecutar este último comando. Intenté con $var, pero el resultado no es correcto (si ejecuto manualmente el comando funciona bien, así que no hay problema). ¿Cuál es la forma correcta de hacer esto?

PD: Claro que podría hacer todo el trabajo en Perl, pero estoy tratando de aprender de esta manera, porque podría ayudarme en otras situaciones.

Barata
fuente

Respuestas:

215

Solo necesitas hacer:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
$(perl test.pl test2 $count)

Sin embargo, si desea llamar a su comando Perl más tarde y es por eso que desea asignarlo a una variable, entonces:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var="perl test.pl test2 $count" # You need double quotes to get your $count value substituted.

...stuff...

eval $var

Según la ayuda de Bash:

~$ help eval
eval: eval [arg ...]
    Execute arguments as a shell command.

    Combine ARGs into a single string, use the result as input to the shell,
    and execute the resulting commands.

    Exit Status:
    Returns exit status of command or success if command is null.
hmontoliu
fuente
176

Probablemente estés buscando eval $var.

August Karlstrom
fuente
3
Esto funcionó cuando $($cmd))falló. Siempre dice comando no encontrado. ¡Gracias!
CMCDragonkai
2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

solo con su archivo en su lugar.

En este ejemplo, utilicé el archivo / etc / password, usando la variable especial ${RANDOM}(sobre la que aprendí aquí), y la sedexpresión que tenía, la única diferencia es que estoy usando comillas dobles en lugar de simples para permitir la expansión de la variable.

nhed
fuente
2

En el caso de que usted tiene múltiples variables que contienen los argumentos de un comando que se está ejecutando, y no sólo una sola cadena, se debe no utilizar eval directamente, ya que se producirá un error en el siguiente caso:

function echo_arguments() {
  echo "Argument 1: $1"
  echo "Argument 2: $2"
  echo "Argument 3: $3"
  echo "Argument 4: $4"
}

# Note we are passing 3 arguments to `echo_arguments`, not 4
eval echo_arguments arg1 arg2 "Some arg"

Resultado:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some
Argument 4: arg

Tenga en cuenta que aunque "Algunos argumentos" se pasaron como un argumento único, evalléalo como dos.

En cambio, puede usar la cadena como el comando en sí:

# The regular bash eval works by jamming all its arguments into a string then
# evaluating the string. This function treats its arguments as individual
# arguments to be passed to the command being run.
function eval_command() {
  "$@";
}

Tenga en cuenta la diferencia entre la salida de evaly la nueva eval_commandfunción:

eval_command echo_arguments arg1 arg2 "Some arg"

Resultado:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some arg
Argument 4:
Ajedi32
fuente
1
Para evitar la evaluación de cada elemento después de espacio, como en el primer ejemplo con eval, envolverlo con comillas simples: eval 'echo_arguments arg1 arg2 "Some arg"'. Entonces la salida será como en su segundo ejemplo.
Noam Manos