Script Bash - conteúdo variável como um comando para executar

159

Eu tenho um script Perl que me fornece uma lista definida de números aleatórios que correspondem às linhas de um arquivo. Em seguida, quero extrair essas linhas do arquivo usando sed.

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

A variável varretorna uma saída como: cat last_queries.txt | sed -n '12p;500p;700p'. O problema é que não consigo executar este último comando. Eu tentei com $var, mas a saída não está correta (se eu executar manualmente o comando ele funciona bem, então não há problema). Qual é a maneira correta de fazer isso?

PS: Claro que eu poderia fazer todo o trabalho em Perl, mas estou tentando aprender dessa maneira, porque isso poderia me ajudar em outras situações.

Barata
fonte

Respostas:

215

Você só precisa fazer:

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

No entanto, se você deseja chamar seu comando Perl posteriormente, e é por isso que deseja atribuí-lo a uma variável, então:

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

De acordo com a ajuda 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
fonte
176

Você provavelmente está procurando eval $var.

August Karlstrom
fonte
3
Isso funcionou quando $($cmd))falhou. Ele sempre diz que o comando não foi encontrado. Obrigado!
precisa saber é o seguinte
2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

apenas com o seu arquivo.

Neste exemplo, usei o arquivo / etc / password, usando a variável especial ${RANDOM}(sobre a qual aprendi aqui) e a sedexpressão que você teve, a única diferença é que estou usando aspas duplas em vez de simples para permitir a expansão da variável.

nhed
fonte
2

No caso em que você tem múltiplas variáveis contendo os argumentos para um comando que você está executando, e não apenas uma única corda, você deve não usar eval diretamente, como ele irá falhar no seguinte 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

Observe que, embora "Algum argumento" tenha sido passado como um único argumento, evalleia-o como dois.

Em vez disso, você pode simplesmente usar a string como o próprio comando:

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

Observe a diferença entre a saída evale a nova eval_commandfunção:

eval_command echo_arguments arg1 arg2 "Some arg"

Resultado:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some arg
Argument 4:
Ajedi32
fonte
1
Para evitar a avaliação de cada elemento após espaço, como em seu primeiro exemplo com eval, envolvê-lo com aspas simples: eval 'echo_arguments arg1 arg2 "Some arg"'. Então a saída será como no seu segundo exemplo.
Noam Manos