Tôi đã viết một tập lệnh bash và tình cờ cập nhật mã (đã lưu tệp tập lệnh vào đĩa) trong khi tập lệnh đang chờ một số đầu vào trong một while
vòng lặp. Sau khi tôi trở lại thiết bị đầu cuối và tiếp tục với lời gọi trước đó của tập lệnh, bash đã báo lỗi về cú pháp tệp:
/home/aularon/bin/script: line 58: unexpected EOF while looking for matching `"'
/home/aularon/bin/script: line 67: syntax error: unexpected end of file
Vì vậy, tôi đã cố gắng làm như sau:
Thứ 1: tạo tập lệnh, self-update.sh
hãy gọi nó là:
#!/bin/bash
fname=$(mktemp)
cat $0 | sed 's/BEFORE\./AFTER!./' > $fname
cp $fname $0
rm -f $fname
echo 'String: BEFORE.';
Những gì kịch bản làm là đọc mã của nó, thay đổi từ 'TRƯỚC' thành 'SAU', sau đó tự viết lại bằng mã mới.
Chạy thứ 2 :
chmod +x self-update.sh
./self-update.sh
Kỳ quan thứ 3 ...
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
Bây giờ, tôi đã không đoán được rằng trong cùng một lời mời, nó sẽ xuất ra SAU! , trên lần chạy thứ hai chắc chắn, nhưng không phải trên lần đầu tiên.
Vì vậy, câu hỏi của tôi là: nó có chủ ý (theo thiết kế)? hoặc là do cách bash chạy tập lệnh? Từng dòng hoặc lệnh bằng lệnh. Có bất kỳ sử dụng tốt của hành vi như vậy? Bất kỳ ví dụ về nó?
Chỉnh sửa: Tôi đã thử định dạng lại tệp để đặt tất cả lệnh vào một dòng, hiện tại nó không hoạt động:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;echo 'String: BEFORE.';
Đầu ra:
aularon@aularon-laptop:~$ ./self-update.sh #First invocation
String: BEFORE.
aularon@aularon-laptop:~$ ./self-update.sh #Second invocation
String: AFTER!.
Trong khi khi di chuyển echo
chuỗi sang dòng tiếp theo, hãy tách chuỗi đó khỏi cp
lệnh gọi viết lại ( ):
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;
echo 'String: BEFORE.';
Và bây giờ nó hoạt động trở lại:
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.