Bash-Skript - variabler Inhalt als auszuführender Befehl

159

Ich habe ein Perl-Skript, das mir eine definierte Liste von Zufallszahlen gibt, die den Zeilen einer Datei entsprechen. Als nächstes möchte ich diese Zeilen mit aus der Datei extrahieren sed.

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

Die Variable vargibt eine Ausgabe zurück wie : cat last_queries.txt | sed -n '12p;500p;700p'. Das Problem ist, dass ich diesen letzten Befehl nicht ausführen kann. Ich habe es mit versucht $var, aber die Ausgabe ist nicht korrekt (wenn ich den Befehl manuell ausführe, funktioniert er einwandfrei, also kein Problem). Was ist der richtige Weg, um dies zu tun?

PS: Sicher, ich könnte die ganze Arbeit in Perl erledigen, aber ich versuche auf diese Weise zu lernen, weil es mir in anderen Situationen helfen könnte.

Barata
quelle

Antworten:

215

Sie müssen nur tun:

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

Wenn Sie Ihren Perl-Befehl jedoch später aufrufen möchten und ihn daher einer Variablen zuweisen möchten, gehen Sie wie folgt vor:

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

Laut Bashs Hilfe:

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

Sie suchen wahrscheinlich eval $var.

August Karlstrom
quelle
3
Dies funktionierte, wenn es $($cmd))fehlschlug. Es heißt immer Befehl nicht gefunden. Vielen Dank!
CMCDragonkai
2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

stattdessen nur mit Ihrer Datei.

In diesem Beispiel habe ich die Datei / etc / password unter Verwendung der speziellen Variablen ${RANDOM}(über die ich hier erfahren habe) und des sedAusdrucks verwendet, den Sie hatten. Der einzige Unterschied besteht darin, dass ich doppelte Anführungszeichen anstelle von einfachen verwende, um die Variablenerweiterung zu ermöglichen.

nhed
quelle
2

In dem Fall, haben Sie mehrere Variablen , die Argumente für einen Befehl enthalten , die Sie laufen lassen , und nicht nur eine einzelne Zeichenfolge, Sie sollten nicht eval direkt verwenden, wie es im folgenden Fall fehlschlagen wird:

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"

Ergebnis:

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

Beachten Sie, dass "Some arg" zwar als einzelnes Argument übergeben wurde, evales jedoch als zwei gelesen wird.

Stattdessen können Sie die Zeichenfolge einfach als Befehl selbst verwenden:

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

Beachten Sie den Unterschied zwischen der Ausgabe von evalund der neuen eval_commandFunktion:

eval_command echo_arguments arg1 arg2 "Some arg"

Ergebnis:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some arg
Argument 4:
Ajedi32
quelle
1
Um zu vermeiden, dass jedes Element nach dem Leerzeichen ausgewertet wird, wie in Ihrem ersten Beispiel mit eval, schließen Sie es in einfache Anführungszeichen ein : eval 'echo_arguments arg1 arg2 "Some arg"'. Dann wird die Ausgabe wie in Ihrem zweiten Beispiel sein.
Noam Manos