Mở rộng so với mở rộng chuỗi không trích dẫn


11
  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

Tôi hiểu tại sao 1 khác với 2. Nhưng tại sao 3 lại cho đầu ra khác với 2? Hãy giải thích đầu ra quá. Làm thế nào để báo giá làm việc trên dòng mới?



Câu trả lời:


19

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 $IFSbiế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à forlặ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 echolệnh (và đưa echora 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 $IFStươ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 xrandrkhô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 inphần của forvò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='
'

4

Một dòng mới được trích dẫn là một dòng mới. Vì vậy, echo "$1"đưa ra một đối số dòng lệnh duy nhất cho echo, sau đó in các dòng mới trực tiếp.

Một dòng mới không trích dẫn là khoảng trắng. Vì vậy, echo $1đưa ra nhiều đối số dòng lệnh cho echo, trong đó in chúng lần lượt với nhau bằng khoảng trắng.


Một dòng mới không được trích dẫn là khoảng trắng là một chút quá ngắn để thực sự hữu ích như là một lời giải thích về hành vi ở đây IMO.
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.