Một biến không được trích dẫn (như trong $var
) hoặc thay thế lệnh (như trong $(cmd)
hoặc `cmd`
) là toán tử split + global trong các shell giống như Bourne.
Nghĩa là, nội dung của chúng được phân chia theo giá trị hiện tại của $IFS
biến đặc biệt (theo mặc định chứa không gian, tab và ký tự dòng mới)
Và sau đó mỗi từ kết quả của tách đó là tùy thuộc vào thế hệ tên tập tin (còn gọi là globbing hoặc mở rộng tên tập tin ), nghĩa là, họ được coi là mô hình và được mở rộng vào danh sách các file mà trận đấu rằng mẫu.
Vì vậy, trong for i in $(xrandr)
, những $(xrandr)
, bởi vì nó không nằm trong dấu ngoặc kép, được tách ra trên trình tự của vũ trụ, tab và ký tự xuống dòng. Và mỗi từ kết quả của việc chia tách đó được kiểm tra để tìm tên tệp phù hợp (hoặc còn lại như thể chúng không khớp với bất kỳ tệp nào) và for
lặp lại tất cả chúng.
Trong đó for i in "$(xrandr)"
, chúng tôi không sử dụng toán tử split + global khi thay thế lệnh được trích dẫn, do đó, có một đường chuyền trong vòng lặp trên một giá trị: đầu ra của xrandr
(không có các ký tự dòng mới kéo theo dải thay thế lệnh ).
Tuy nhiên echo $i
, trong , không $i
được trích dẫn một lần nữa, do đó, một lần nữa nội dung $i
được phân tách và tùy thuộc vào việc tạo tên tệp và chúng được truyền dưới dạng các đối số riêng biệt cho echo
lệnh (và đưa echo
ra các đối số được phân tách bằng khoảng trắng).
Vì vậy, bài học kinh nghiệm:
- nếu bạn không muốn tách từ hoặc tạo tên tệp , hãy luôn trích dẫn mở rộng biến và thay thế lệnh
- nếu bạn muốn tách từ hoặc tạo tên tệp , hãy để chúng không được trích dẫn nhưng được đặt
$IFS
tương ứng và / hoặc bật hoặc tắt tạo tên tệp nếu cần ( set -f
, set +f
).
Thông thường, trong ví dụ của bạn ở trên, nếu bạn muốn lặp qua danh sách các từ được phân tách trống trong đầu ra của xrandr
, bạn cần phải:
- để
$IFS
ở giá trị mặc định của nó (hoặc bỏ đặt nó) để phân chia trên khoảng trống
- Sử dụng
set -f
để vô hiệu hóa việc tạo tên tệp trừ khi bạn chắc chắn rằng xrandr
không bao giờ xuất bất kỳ *
hoặc ?
hoặc [
ký tự nào (là các ký tự đại diện được sử dụng trong các mẫu tạo tên tệp)
Và sau đó chỉ sử dụng toán tử split + global (chỉ để lại thay thế lệnh hoặc mở rộng biến không được trích dẫn) trong in
phần của for
vòng lặp:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Nếu bạn muốn để lặp qua (không rỗng) dòng của xrandr
đầu ra, bạn cần phải thiết lập $IFS
để kí tự xuống dòng:
IFS='
'