Bash-Aliase werden auch mit shopt expand_aliases nicht erweitert

8

Ich möchte einen Alias ​​in einem bash -cKonstrukt ausführen .

Das bashHandbuch sagt:

Aliase werden nicht erweitert, wenn die Shell nicht interaktiv ist, es sei denn, die expand_aliasesShell-Option wird mit festgelegtshopt

Warum wird in diesem Beispiel der Alias hibeim expand_aliasesexpliziten Festlegen nicht gefunden ?

% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases  on
bash: hi: command not found

Ich renne GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).

Kontext: Ich möchte in der Lage sein, einen Alias ​​mit Leerlaufpriorität auszuführen, z. B. ein Skript mit:

#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"

Ich möchte die Verwendung vermeiden, bash -ida ich nicht möchte, dass meine .bashrcgelesen wird.

Tom Hale
quelle
3
Der Absatz direkt nach der zitierten Anweisung aus dem Bash-Handbuch scheint dies zu behandeln: '... Aliase werden erweitert, wenn ein Befehl gelesen wird, nicht, wenn er ausgeführt wird. Daher wird eine Aliasdefinition, die in derselben Zeile wie ein anderer Befehl angezeigt wird, erst wirksam, wenn die nächste Eingabezeile gelesen wird. Die Befehle, die der
Aliasdefinition
Wie in den meisten Fällen sollten Sie hier die Verwendung einer Shell-Funktion anstelle eines Alias ​​in Betracht ziehen. bash -c "hi () { echo hello; }; hi"Ausgänge hello.
Chepner

Antworten:

16

Es scheint nicht zu funktionieren, wenn Sie den Alias ​​in derselben Zeile festlegen, in der er verwendet wird. Wahrscheinlich etwas damit zu tun, wie Aliase sehr früh in der Befehlszeilenverarbeitung vor der eigentlichen Analysephase erweitert werden. Auf einer interaktiven Shell:

$ alias foo
bash: alias: foo: not found
$ alias foo='echo foo'; foo         # 2 
bash: foo: command not found
$ alias foo='echo bar'; foo         # 3
foo
$ foo
bar

Beachten Sie, dass der verwendete Alias ​​eine Zeile zu spät ist: Beim zweiten Befehl wird der gerade festgelegte Alias ​​nicht gefunden, und beim dritten Befehl wird der zuvor festgelegte verwendet.

Es funktioniert also, wenn wir eine neue Zeile in die -cZeichenfolge einfügen :

$ bash -c $'shopt -s expand_aliases; alias foo="echo foo";\n foo'
foo

(Sie können auch verwenden, bash -O expand_aliases -c ...anstatt shoptinnerhalb des Skripts zu verwenden, nicht dass es bei der Newline hilft.)

Alternativ können Sie eine Shell-Funktion anstelle eines Alias ​​verwenden. Sie sind auch auf andere Weise viel besser:

$ bash -c 'foo() { echo foo; }; foo'
foo
ilkkachu
quelle
14

Meinen Kommentar in eine Antwort verwandeln, wie von ilkkachu vorgeschlagen.

Das Bash-Handbuch (in der Frage verlinkt) enthält eine Erläuterung zum Umgang mit Aliasen, wenn sich in derselben Zeile eine Aliasdefinition und ein Befehl befinden.

Zitat (aus Gründen der Übersichtlichkeit leicht formatiert):

Die Regeln für die Definition und Verwendung von Aliasen sind etwas verwirrend. Bash liest immer mindestens eine vollständige Eingabezeile und alle Zeilen, aus denen ein zusammengesetzter Befehl besteht, bevor einer der Befehle in dieser Zeile oder der zusammengesetzte Befehl ausgeführt wird.

Aliase werden erweitert, wenn ein Befehl gelesen wird, nicht wenn er ausgeführt wird. Daher wird eine Aliasdefinition, die in derselben Zeile wie ein anderer Befehl angezeigt wird, erst wirksam, wenn die nächste Eingabezeile gelesen wird. Die Befehle, die der Aliasdefinition in dieser Zeile folgen, sind vom neuen Alias ​​nicht betroffen.

Dieses Verhalten ist auch ein Problem, wenn Funktionen ausgeführt werden. Aliase werden beim Lesen einer Funktionsdefinition erweitert, nicht beim Ausführen der Funktion, da eine Funktionsdefinition selbst ein Befehl ist. Infolgedessen sind in einer Funktion definierte Aliase erst verfügbar, nachdem diese Funktion ausgeführt wurde.

Fügen Sie aus Sicherheitsgründen Aliasdefinitionen immer in eine separate Zeile ein und verwenden Sie keinen Alias ​​in zusammengesetzten Befehlen.

Die Antwort von ilkkachu bietet mehrere mögliche Lösungen für dieses Problem.

Haxiel
quelle
FWIW, ich habe Ihren letzten Kommentar gesehen, hatte aber keine Zeit zu antworten. Es ist keine schlechte Sache, wenn Antworten andere ergänzen, und zu wissen, dass sie tatsächlich so dokumentiert sind, ist nützlich. Also danke, dass du das geschrieben hast, jetzt kann ich es positiv bewerten. :)
ilkkachu