はいbash、特にシェルはファイルを一度に1行ずつ読み取るように注意しているため、対話的に使用する場合と同じように機能します。
ファイルがシーク可能でない場合(パイプなど)、文字をbash超えて読み取らないように、一度に1バイトも読み取ります\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'
UTF-8でエンコードされたU + 00E9を出力します。ただし、次のように変更すると:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
\ue9コマンドは、この場合、ある解析された時点で有効であった文字セットに展開する前に、exportコマンドが実行されます。
また、いくつかのシェルでsourceaka .コマンドを使用すると、ソースファイルにも同じ種類の問題が発生することに注意してください。
bashただし、sourceコマンドがファイルを解釈する前に完全に読み取る場合は、そうではありません。bash具体的に記述している場合、スクリプトの先頭に追加することで、実際にそれを利用できます。
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(将来のバージョンでbashは、現在制限と見なされている動作を変更できると想像できるので、これに依存しません(bashとAT&T kshは、そのように動作する唯一のPOSIXのようなシェルです)already_sourced変数が環境にないことを前提としているため、このトリックは少し脆弱です。もちろん、BASH_SOURCE変数の内容に影響することは言うまでもありません)