Skrypt Bash - zmienna zawartość jako polecenie do uruchomienia


159

Mam skrypt Perla, który daje mi zdefiniowaną listę losowych liczb odpowiadających wierszom pliku. Następnie chcę wyodrębnić te wiersze z pliku za pomocą sed.

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

Zmienna varzwraca wyjście jak: cat last_queries.txt | sed -n '12p;500p;700p'. Problem w tym, że nie mogę uruchomić tego ostatniego polecenia. Próbowałem $var, ale wynik nie jest poprawny (jeśli uruchomię ręcznie polecenie, działa dobrze, więc nie ma problemu). Jaki jest właściwy sposób, aby to zrobić?

PS: Jasne, że mógłbym wykonać całą pracę w Perlu, ale staram się uczyć w ten sposób, ponieważ może mi to pomóc w innych sytuacjach.

Odpowiedzi:


215

Wystarczy, że:

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

Jeśli jednak chcesz później wywołać polecenie Perla i dlatego chcesz przypisać je do zmiennej, to:

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

Zgodnie z pomocą Basha:

~$ 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

po prostu z plikiem.

W tym przykładzie użyłem pliku / etc / password, używając specjalnej zmiennej ${RANDOM}(o której się tutaj dowiedziałem) i sedwyrażenia, które miałeś, jedyną różnicą jest to, że używam podwójnych cudzysłowów zamiast pojedynczych, aby umożliwić rozwinięcie zmiennej.


2

W przypadku, gdy masz wiele zmiennych zawierających argumenty dla polecenia używasz, a nie tylko jeden ciąg, należy nie używać eval bezpośrednio, ponieważ nie będą mogły w następującym przypadku:

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"

Wynik:

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

Zauważ, że nawet jeśli „Some arg” został przekazany jako pojedynczy argument, należy evalgo odczytać jako dwa.

Zamiast tego możesz po prostu użyć ciągu jako samego polecenia:

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

Zauważ różnicę między wyjściem evala nową eval_commandfunkcję:

eval_command echo_arguments arg1 arg2 "Some arg"

Wynik:

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

1
Aby uniknąć oceny każdego elementu po przestrzeni, jak w pierwszym przykładzie z eval, owinąć go z apostrofami: eval 'echo_arguments arg1 arg2 "Some arg"'. Wtedy wynik będzie taki jak w drugim przykładzie.
Noam Manos
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.