Да, оболочки, bash
в частности, внимательно читают файл по одной строке за раз, поэтому он работает так же, как при интерактивном использовании.
Вы заметите, что когда файл не доступен для поиска (например, канал), bash
даже читает по одному байту за раз, чтобы не читать после \n
символа. Когда файл доступен для поиска, он оптимизирует, считывая полные блоки за раз, но возвращаясь к после \n
.
Это означает, что вы можете делать такие вещи, как:
bash << \EOF
read var
var's content
echo "$var"
EOF
Или написать сценарии, которые обновляются сами. Что бы вы не смогли сделать, если бы это не дало вам такой гарантии.
Сейчас редко можно делать подобные вещи, и, как вы узнали, эта функция имеет тенденцию мешать чаще, чем полезна.
Чтобы избежать этого, вы можете попробовать и убедиться , что вы не измените файл на месте (например, изменить копию и переместите копию на месте (например , sed -i
или perl -pi
и некоторые редакторы делают, например)).
Или вы можете написать свой сценарий как:
{
sleep 20
echo test
}; exit
(обратите внимание, что важно, чтобы он exit
находился на одной линии с }
; хотя вы могли бы также поместить его в фигурные скобки непосредственно перед закрывающей).
или:
main() {
sleep 20
echo test
}
main "$@"; exit
Оболочке нужно будет прочитать скрипт до тех пор, пока он exit
не начнет что-либо делать. Это гарантирует, что оболочка не будет читать из сценария снова.
Это означает, что весь скрипт будет храниться в памяти.
Это также может повлиять на синтаксический анализ сценария.
Например, в bash
:
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
Выведет, что U + 00E9 закодировано в UTF-8. Однако, если вы измените его на:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
\ue9
Будет расширены в кодировке , которая была в действии в то время, когда команда была разобрана , который в этом случае , прежде чемexport
команда будет выполнена.
Также обратите внимание, что если команда source
aka .
используется с некоторыми оболочками, у вас возникнет та же проблема с исходными файлами.
Это не тот случай, bash
когда чья source
команда полностью читает файл перед его интерпретацией. Если писать bash
специально, вы можете использовать это, добавив в начале сценария:
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(Я бы не стал полагаться на это, хотя, как вы могли себе представить, будущие версии bash
могут изменить это поведение, которое в настоящее время можно рассматривать как ограничение (bash и AT & T ksh - единственные POSIX-подобные оболочки, которые, насколько можно судить, ведут себя так же) и already_sourced
хитрость немного хрупкая, так как она предполагает, что переменная находится вне среды, не говоря уже о том, что она влияет на содержимое переменной BASH_SOURCE)