Bash script - konten variabel sebagai perintah untuk dijalankan

159

Saya memiliki skrip Perl yang memberi saya daftar angka acak yang ditentukan yang sesuai dengan baris file. Selanjutnya saya ingin mengekstrak baris-baris itu dari file menggunakan sed.

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

Variabel varmengembalikan sebuah output seperti: cat last_queries.txt | sed -n '12p;500p;700p'. Masalahnya adalah saya tidak bisa menjalankan perintah terakhir ini. Saya mencoba $var, tetapi hasilnya tidak benar (jika saya menjalankan secara manual perintah itu berfungsi dengan baik, jadi tidak ada masalah di sana). Apa cara yang benar untuk melakukan ini?

PS: Tentu saya bisa melakukan semua pekerjaan di Perl, tetapi saya mencoba belajar dengan cara ini, karena bisa membantu saya dalam situasi lain.

Barata
sumber

Jawaban:

215

Anda hanya perlu melakukan:

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

Namun, jika Anda ingin memanggil perintah Perl Anda nanti, dan itulah mengapa Anda ingin menetapkannya ke variabel, kemudian:

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

Sesuai bantuan 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
sumber
176

Anda mungkin sedang mencari eval $var.

August Karlstrom
sumber
3
Ini berfungsi ketika $($cmd))gagal. Itu selalu mengatakan perintah tidak ditemukan. Terima kasih!
CMCDragonkai
2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

hanya dengan file Anda saja.

Dalam contoh ini saya menggunakan file / etc / password, menggunakan variabel khusus ${RANDOM}(yang saya pelajari di sini), dan sedekspresi yang Anda miliki, satu-satunya perbedaan adalah bahwa saya menggunakan tanda kutip ganda dan bukan tunggal untuk memungkinkan ekspansi variabel.

nhed
sumber
2

Dalam kasus di mana Anda memiliki banyak variabel yang berisi argumen untuk perintah yang Anda jalankan, dan bukan hanya satu string, Anda tidak boleh menggunakan eval secara langsung, karena akan gagal dalam kasus berikut:

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"

Hasil:

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

Perhatikan bahwa meskipun "Some arg" diajukan sebagai satu argumen, evalbacalah sebagai dua.

Sebagai gantinya, Anda bisa menggunakan string sebagai perintah itu sendiri:

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

Perhatikan perbedaan antara output evaldan eval_commandfungsi baru :

eval_command echo_arguments arg1 arg2 "Some arg"

Hasil:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some arg
Argument 4:
Ajedi32
sumber
1
Untuk menghindari evaluasi setiap elemen setelah ruang, seperti dalam contoh pertama Anda dengan eval, bungkus dengan tanda kutip tunggal: eval 'echo_arguments arg1 arg2 "Some arg"'. Maka hasilnya akan seperti pada contoh kedua Anda.
Noam Manos