Có shell, và bash
đặc biệt, cẩn thận để đọc từng dòng một tệp, vì vậy nó hoạt động tương tự như khi bạn sử dụng nó một cách tương tác.
Bạn sẽ nhận thấy rằng khi tệp không thể tìm kiếm được (như một đường ống), bash
thậm chí đọc từng byte một lần để đảm bảo không đọc qua \n
ký tự. Khi tệp có thể tìm kiếm, nó sẽ tối ưu hóa bằng cách đọc các khối đầy đủ tại một thời điểm, nhưng tìm kiếm trở lại sau \n
.
Điều đó có nghĩa là bạn có thể làm những việc như:
bash << \EOF
read var
var's content
echo "$var"
EOF
Hoặc viết kịch bản tự cập nhật. Điều mà bạn sẽ không thể làm nếu nó không mang lại cho bạn sự đảm bảo đó.
Bây giờ, thật hiếm khi bạn muốn làm những việc như vậy và, như bạn phát hiện ra, tính năng đó có xu hướng trở nên thường xuyên hơn là hữu ích.
Để tránh điều đó, bạn có thể thử và đảm bảo rằng bạn không sửa đổi tệp tại chỗ (ví dụ: sửa đổi một bản sao và di chuyển bản sao tại chỗ (ví dụ như sed -i
hoặc perl -pi
một số biên tập viên thực hiện)).
Hoặc bạn có thể viết kịch bản của bạn như:
{
sleep 20
echo test
}; exit
(lưu ý rằng điều quan trọng là exit
phải nằm trên cùng một đường với }
; mặc dù bạn cũng có thể đặt nó bên trong niềng răng ngay trước khi đóng).
hoặc là:
main() {
sleep 20
echo test
}
main "$@"; exit
Shell sẽ cần đọc kịch bản cho đến exit
trước khi bắt đầu làm bất cứ điều gì. Điều đó đảm bảo shell sẽ không đọc lại từ script.
Điều đó có nghĩa là toàn bộ tập lệnh sẽ được lưu trữ trong bộ nhớ.
Điều đó cũng có thể ảnh hưởng đến việc phân tích cú pháp của tập lệnh.
Ví dụ bash
: trong :
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
Sẽ xuất ra rằng U + 00E9 được mã hóa trong UTF-8. Tuy nhiên, nếu bạn thay đổi nó thành:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
Các \ue9
sẽ được mở rộng trong charset đó là có hiệu lực tại thời điểm mà lệnh đã được phân tích trong trường hợp này là trước khi các export
lệnh được thực thi.
Cũng lưu ý rằng nếu lệnh source
aka .
được sử dụng, với một số shell, bạn sẽ gặp vấn đề tương tự đối với các tệp có nguồn gốc.
Đó không phải là trường hợp bash
mặc dù source
lệnh của bạn đọc tệp đầy đủ trước khi diễn giải nó. Nếu viết bash
cụ thể, bạn thực sự có thể sử dụng điều đó, bằng cách thêm vào lúc bắt đầu tập lệnh:
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(Tôi sẽ không dựa vào điều đó mặc dù bạn có thể tưởng tượng các phiên bản trong tương lai bash
có thể thay đổi hành vi đó hiện được coi là hạn chế (bash và AT & T ksh là những vỏ giống như POSIX duy nhất hoạt động như vậy theo như có thể nói) và already_sourced
mẹo này hơi dễ vỡ vì nó giả sử rằng biến đó không có trong môi trường, chưa kể đến việc nó ảnh hưởng đến nội dung của biến BASH_SOURCE)