Oui, les shells, et bashen particulier, veillent à lire le fichier ligne par ligne, de sorte qu'il fonctionne de la même manière que lorsque vous l'utilisez de manière interactive.
Vous remarquerez que lorsque le fichier ne peut pas être recherché (comme un tube), bashmême lit un octet à la fois pour être sûr de ne pas lire après le \ncaractère. Lorsque le fichier peut être recherché, il optimise en lisant des blocs entiers à la fois, mais en recherchant après \n.
Cela signifie que vous pouvez faire des choses comme:
bash << \EOF
read var
var's content
echo "$var"
EOF
Ou écrivez des scripts qui se mettent à jour. Ce que vous ne pourriez pas faire si cela ne vous donnait pas cette garantie.
Maintenant, il est rare que vous souhaitiez faire de telles choses et, comme vous l'avez découvert, cette fonctionnalité a tendance à gêner plus souvent qu'elle n'est utile.
Pour éviter cela, vous pouvez essayer de vous assurer que vous ne modifiez pas le fichier sur place (par exemple, modifiez une copie et déplacez la copie sur place (comme sed -iou perl -piet certains éditeurs le font par exemple)).
Ou vous pouvez écrire votre script comme:
{
sleep 20
echo test
}; exit
(Notez qu'il est important que le exitsoit sur la même ligne que }, bien que vous puissiez aussi le mettre entre les accolades juste avant le dernier).
ou:
main() {
sleep 20
echo test
}
main "$@"; exit
Le shell devra lire le script jusqu’à exitavant de commencer à faire quoi que ce soit. Cela garantit que le shell ne lira plus le script.
Cela signifie que tout le script sera stocké dans la mémoire.
Cela peut également affecter l'analyse du script.
Par exemple, dans bash:
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
Produirait que U + 00E9 codé en UTF-8. Cependant, si vous le changez en:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
La \ue9volonté sera développée dans le jeu de caractères qui était en vigueur au moment de l'analyse de la commande et qui, dans ce cas, est antérieure à l' exportexécution de la commande.
Notez également que si la commande sourceaka .est utilisée, avec certains shells, vous aurez le même genre de problème pour les fichiers sourcés.
Ce n'est pas le cas de bashbien dont la sourcecommande lit le fichier complètement avant de l'interpréter. Si vous écrivez bashspécifiquement, vous pouvez en faire usage en ajoutant au début du script:
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(Je ne m'appuierais pas là-dessus, même si, comme vous pouvez l'imaginer, les versions futures bashpourraient changer ce comportement qui peut actuellement être considéré comme une limitation (bash et AT & T ksh sont les seuls shells de type POSIX qui se comportent comme ça autant que l'on peut en juger) et l' already_sourcedastuce est un peu fragile car elle suppose que la variable n'est pas dans l'environnement, sans parler du fait qu'elle affecte le contenu de la variable BASH_SOURCE)