Script Bash: contenuto variabile come comando da eseguire


159

Ho uno script Perl che mi dà un elenco definito di numeri casuali che corrispondono alle righe di un file. Quindi voglio estrarre quelle righe dal file usando sed.

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

La variabile varrestituisce un output come: cat last_queries.txt | sed -n '12p;500p;700p'. Il problema è che non riesco a eseguire quest'ultimo comando. Ho provato con $var, ma l'output non è corretto (se eseguo manualmente il comando funziona bene, quindi nessun problema lì). Qual è il modo corretto per farlo?

PS: Sicuro che avrei potuto fare tutto il lavoro in Perl, ma sto cercando di imparare in questo modo, perché potrebbe aiutarmi in altre situazioni.

Risposte:


215

Devi solo fare:

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

Tuttavia, se vuoi chiamare il tuo comando Perl in un secondo momento, ed è per questo che vuoi assegnarlo a una variabile, allora:

#!/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

Secondo l'aiuto di 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.


2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

solo con il tuo file invece.

In questo esempio ho usato il file / etc / password, usando la variabile speciale ${RANDOM}(di cui ho imparato qui), e l' sedespressione che hai avuto, l'unica differenza è che sto usando virgolette doppie anziché singole per consentire l'espansione della variabile.


2

Nel caso in cui si dispone di più variabili contenenti gli argomenti per un comando si sta eseguendo, e non solo una singola stringa, è necessario non usare eval direttamente, come fallirà nei seguenti casi:

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"

Risultato:

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

Nota che anche se "Some arg" è stato passato come argomento singolo, evalleggilo come due.

Invece, puoi semplicemente usare la stringa come il comando stesso:

# 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() {
  "$@";
}

Nota la differenza tra l'output di evale la nuova eval_commandfunzione:

eval_command echo_arguments arg1 arg2 "Some arg"

Risultato:

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

1
Per evitare la valutazione di ogni elemento dopo che lo spazio, come nel tuo primo esempio con eval, avvolgerlo con apici: eval 'echo_arguments arg1 arg2 "Some arg"'. Quindi l'output sarà come nel tuo secondo esempio.
Noam Manos,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.