Tak, powłoki, a bash
zwłaszcza starają się czytać plik po jednym wierszu na raz, więc działa tak samo, jak podczas korzystania z niego interaktywnie.
Zauważysz, że gdy plik nie jest widoczny (jak potok), bash
odczytuje nawet jeden bajt na raz, aby mieć pewność, że nie przeczyta on \n
znaku. Gdy plik jest widoczny, optymalizuje się, odczytując jednocześnie pełne bloki, ale należy szukać później \n
.
Oznacza to, że możesz robić takie rzeczy jak:
bash << \EOF
read var
var's content
echo "$var"
EOF
Lub pisz skrypty, które same się aktualizują. Nie byłbyś w stanie tego zrobić, gdyby nie dał ci takiej gwarancji.
Teraz rzadko zdarza się, że chcesz robić takie rzeczy i, jak się okazało, funkcja ta przeszkadza częściej niż jest przydatna.
Aby tego uniknąć, można spróbować i upewnij się, że nie należy zmodyfikować plik w miejscu (na przykład zmodyfikować kopię, i przenieść kopię w miejscu (jak sed -i
lub perl -pi
a niektórzy redaktorzy zrobić na przykład)).
Lub możesz napisać skrypt:
{
sleep 20
echo test
}; exit
(zwróć uwagę, że ważne jest, aby exit
znajdować się w tym samym wierszu co }
; chociaż możesz również umieścić go w nawiasach klamrowych tuż przed zamknięciem).
lub:
main() {
sleep 20
echo test
}
main "$@"; exit
Powłoka będzie musiała przeczytać skrypt do momentu, aż exit
zacznie cokolwiek robić. Dzięki temu powłoka nie będzie ponownie czytać ze skryptu.
Oznacza to jednak, że cały skrypt będzie przechowywany w pamięci.
Może to również wpłynąć na parsowanie skryptu.
Na przykład w bash
:
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
Wyprowadziłby kod U + 00E9 zakodowany w UTF-8. Jeśli jednak zmienisz go na:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
\ue9
Zostanie poszerzona w charset, który był w rzeczywistości w tym czasie, że rozkaz został przeanalizowany, która w tym przypadku jest przedexport
komenda jest wykonywana.
Zauważ też, że jeśli użyjesz polecenia source
aka .
, z niektórymi powłokami, będziesz miał ten sam problem z plikami źródłowymi.
Nie dzieje się tak w przypadku, bash
gdy source
komenda odczytuje plik w całości przed jego interpretacją. Jeśli piszesz bash
specjalnie, możesz z tego skorzystać, dodając na początku skryptu:
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(Nie polegałbym jednak na tym, ponieważ można sobie wyobrazić, że przyszłe wersje bash
mogłyby zmienić to zachowanie, które może być obecnie postrzegane jako ograniczenie (bash i AT&T ksh są jedynymi powłokami podobnymi do POSIX, które zachowują się tak daleko, o ile są w stanie powiedzieć) a already_sourced
trik jest nieco kruchy, ponieważ zakłada, że zmienna nie znajduje się w środowisku, nie wspominając już o tym, że wpływa na zawartość zmiennej BASH_SOURCE)