Ausführen von Befehlen, die in Shell-Variablen gespeichert sind

7

Folgendes funktioniert in meiner Shell (zsh):

> FOO='ls'
> $FOO
file1 file2

aber das nicht:

> FOO='emacs -nw'
> $FOO
zsh: command not found: emacs -nw

obwohl das emacs -nwdirekte Aufrufen Emacs perfekt öffnet.

Warum?

Amelio Vazquez-Reina
quelle
1
Sind die Backticks in Ihrem 2. Befehl nur OCR-Fehler oder haben Sie sie wirklich in Ihrem Skript verwendet?
versuchen-fangen-endlich
1
Nur als Bemerkung: In Bash würde das funktionieren.
Hauke ​​Laging
1
@HaukeLaging, das würde funktionieren, wenn IFS nicht geändert würde.
Stéphane Chazelas
3
@ try-catch-finally Aber in diesem Fall zeigt die Fehlermeldung, dass er Anführungszeichen und keine Backticks verwendet hat.
Hauke ​​Laging
3
@HaukeLaging, kein Verhalten zshwie erwartet. Bei der Eingabe $cmdwird der Befehl ausgeführt, in dessen Namen gespeichert ist $cmd. bash(und die meisten anderen Bourne wie Muscheln) invoke der Split + glob Operator auf unquoted Variablen zsh festgelegt , dass.
Stéphane Chazelas

Antworten:

8

Weil kein Befehl aufgerufen wird emacs -nw. Es gibt einen Befehl, emacsan den Sie eine -nwOption übergeben können.

Zum Speichern von Befehlen verwenden Sie im Allgemeinen folgende Funktionen :

foo() emacs -nw "$@"
foo ...

Um mehrere Argumente zu speichern, verwenden Sie im Allgemeinen Arrays:

foo=(emacs -nw)
$foo ...

So speichern Sie eine Zeichenfolge, die mehrere durch Leerzeichen getrennte Wörter enthält, und teilen sie in Leerzeichen auf:

foo='emacs -nw'
${(s: :)foo} ...

Sie können sich auf die auf IFS durchgeführte Wortaufteilung verlassen (IFS enthält standardmäßig Leerzeichen, Tabulatoren, Zeilenumbrüche und Null):

foo='emacs -nw'
$=foo ...
Stéphane Chazelas
quelle
Haben Sie die Backticks im 2. Befehl im OP bemerkt?
Try-Catch-Endlich
Danke @Stephane, das ist wie immer sehr hilfreich. Ich hoffe jetzt, diese Antwort im Kontext dieser anderen Frage zu verstehen . Zu diesem Zweck habe ich versucht, >my_wrapper.sh "some text" (date '+%d')wo der my_wrapperBefehl aufgerufen werden soll date '+%d', aber es funktioniert nicht.
Amelio Vazquez-Reina
@ user815423426 - sehen Sie sich hier vielleicht Stéphanes Antwort an . Sie könnten auch einen Blick auf meine eigenen werfen. Das Problem , das Sie haben ist aufgrund der Shell Reihenfolge der Auswertungen , während Befehl Parsen und die (subshell)- der Parser Bedürfnisse diejenigen zugleich erkennt er eine variable Erweiterung lesen - was natürlich nicht passieren kann , wenn die (Pars )sind innerhalb der Expansion. Sie brauchen eval- oder und alias- in irgendeiner Form.
Mikeserv
Egal, das Problem mit dateist auf die Tatsache zurückzuführen, dass es crontaberforderlich ist, %dals @ Gilles hier zu
Amelio Vazquez-Reina
3

Für zukünftige Leser sollte erwähnt werden, dass die "Standard" eval-Methode darin besteht, die in der Variablen gespeicherten Argumente zu verwenden:

eval "$foo"

Man kann den Ausdruck auch mit Befehlssubstitution auswerten:

$(expr "$foo")

echoed Variable (oder anderweitig gedruckt) funktioniert auch:

$(echo "$foo")

Diese Methoden funktionieren zumindest in zshund einwandfrei bash.

jimmij
quelle