Якщо “bash <file>” працює, чому “source <file>” видає помилку?


26

У мене є такий сценарій:

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

Якщо я бігаю bash /tmp/file, aлунає, але якщо я біжу source /tmp/file, я отримую:

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

Вихід:

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

Виведення команд shopt -pта set -o: http://pastebin.com/bsqc8aru

Вихід set: http://pastebin.com/S9KpqZAL

declare -fp нічого не виробляє.

Я думав, що sourceце робить те саме bash, але замість початку нового сеансу швидше запускає код у поточному. Хтось може мені пояснити цю помилку?

Я запускаю bash GNU bash, версія 4.2.53 (1) -release (x86_64-redhat-linux-gnu).


1
Ні, це весь код. Нові рядки - 0a.
knezi

2
@Rahul шістнадцятковий код символу
Unife linefeed

2
Чи є $BASH_ENVнабір?
roaima

2
@PSkocik, що насправді дивно. працює bash -c "source / tmp / test".
knezi

5
А-ха! Будь ласка, додайте, що це працює з bash -cвашим запитанням. Потім, покажіть нам вміст вашого ~/.bashrcфайлу, можливо, там щось накручується.
тердон

Відповіді:


75

Я можу відтворити вашу поведінку, якщо я псевдонім fi:

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

Він працює під час його виконання, але виходить з ладу, коли ви його джерелом, тому що псевдоніми недоступні в неінтерактивних оболонках (тип оболонки, яка виконує сценарії оболонки). Як пояснено у посібнику з bash :

Псевдоніми не розширюються, коли оболонка не є інтерактивною, якщо параметр expand_aliasesоболонки не встановлений за допомогою shopt(див. The Shopt Builtin ).

Однак, коли ви sourceщось робите , він запускається у вашій поточній оболонці, яка, оскільки є інтерактивною, вже завантажила псевдоніми, і тому fiпсевдонім розпізнається та порушує джерело пошуку.


16
Ви абсолютно праві. Я встановив: alias fi = 'find -type f | xargs grep -H '.
knezi

7
Позбавтесь цього aliasзараз! :)
Марк Стюарт

9
Я вражений тим, що комусь вдалося з'ясувати таку незрозумілу проблему. Молодці, сер.
MathematicalOrchid

6
@MathematicalOrchid Я підозрював, що щось було відчужено (через інтерактивну оболонку), setвиключається вихід і alias if='foo "'(остання відкрита цитата дала помилку щодо відсутньої цитати, і тому останній варіант був fi
згладжений
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.