Wenn "bash <file>" funktioniert, warum gibt "source <file>" einen Fehler aus?

26

Ich habe das folgende Skript:

#!/bin/bash
set -x
if :; then
    echo a
fi

Wenn ich renne bash /tmp/file, awird es wiedergegeben, aber wenn ich renne source /tmp/file, bekomme ich:

bash: /tmp/test: line 6: syntax error: unexpected end of file

Die Ausgabe:

knezi@holly tmp]$set -x; source /tmp/test; set +x
+ source /tmp/test
++ set -x
bash: /tmp/test: line 6: syntax error: unexpected end of file
+ set +x

knezi@holly tmp]$set -x; command source /tmp/test; set +x
+ set -x
+ command source /tmp/test
+ source /tmp/test
++ set -x
bash: /tmp/test: line 6: syntax error: unexpected end of file
+ set +x

knezi@holly tmp]$bash -c "source /tmp/test"
+ bash -c 'source /tmp/test'
++ :
++ echo a
a


knezi@holly tmp]$od -c /tmp/test
0000000   #   !   /   b   i   n   /   b   a   s   h  \n   s   e   t    
0000020   -   x  \n   i   f       :   ;       t   h   e   n  \n  \t   e
0000040   c   h   o       a  \n   f   i  \n
0000051

Ausgabe von Befehlen shopt -pund set -o: http://pastebin.com/bsqc8aru

Ausgabe von set: http://pastebin.com/S9KpqZAL

declare -fp produziert nichts.

Ich dachte, das sourcemacht dasselbe wie bash, aber anstatt eine neue Sitzung zu starten, wird der Code in der aktuellen ausgeführt. Kann mir jemand diesen Fehler erklären?

Ich starte bash GNU bash, Version 4.2.53 (1) -release (x86_64-redhat-linux-gnu).

knezi
quelle
1
Nein, das ist der ganze Code. Zeilenumbrüche sind 0a.
Knezi
2
@ Rahul der hexadezimale Code des Unix-Zeilenvorschubzeichens
PSkocik
2
Ist das $BASH_ENVSet?
Roaima
2
@PSkocik das ist echt komisch. bash -c "source / tmp / test" funktioniert.
Knezi
5
Ah-ha! Bitte füge hinzu, dass es mit bash -cdeiner Frage funktioniert . Dann zeigen Sie uns den Inhalt Ihrer ~/.bashrcDatei, da ist wahrscheinlich etwas, das die Dinge vermasselt.
terdon

Antworten:

75

Ich kann Ihr Verhalten reproduzieren, wenn ich einen Alias ​​habe fi:

$ alias fi=:
+ alias fi=:
$ . ./test
+ . ./test
++ set -x
bash: ./test: line 6: syntax error: unexpected end of file

Es funktioniert, wenn Sie es ausführen, schlägt jedoch fehl, wenn Sie es als Quelle verwenden, da Aliase in nicht interaktiven Shells (dem Typ der Shell, die Shellskripts ausführt) nicht verfügbar sind. Wie im Bash-Handbuch erklärt :

Aliase werden nicht erweitert, wenn die Shell nicht interaktiv ist, es sei denn, die expand_aliasesShell-Option wurde mit festgelegt shopt(siehe The Shopt Builtin ).

Wenn Sie jedoch sourceetwas tun, wird es in Ihrer aktuellen Shell ausgeführt, die, da sie interaktiv ist, die Aliase bereits geladen hat und daher den fiAlias ​​erkennt und das Sourcing unterbricht.

muru
quelle
16
Du hast vollkommen recht. Ich habe gesetzt: alias fi = 'find -type f | xargs grep -H '.
Knezi
7
Werde das aliasjetzt los ! :)
Mark Stewart
9
Ich bin erstaunt, dass es irgendjemand geschafft hat, ein so dunkles Problem herauszufinden. Gut gemacht, Sir.
MathematicalOrchid
6
@MathematicalOrchid Ich hatte den Verdacht, dass ein Alias ​​(aufgrund der interaktiven Shell) setvon der Ausgabe ausgeschlossen wurde und alias if='foo "'(ein nachgestelltes offenes Zitat gab einen Fehler über das fehlende Zitat aus, und die letzte Option war Aliasing fi.
muru