thay đổi IFS tạm thời trước vòng lặp for [trùng lặp]

Aug 16 2020

Tôi biết rằng SHELLphép gán biến diễn ra ngay lập tức trước một lệnh, như vậy sẽ IFS=":" read a b c d <<< "$here_string"hoạt động ...

Điều tôi tự hỏi là liệu các phép gán như vậy không hoạt động khi được thực hiện với các câu lệnh ghép như vòng lặp? Tôi đã thử một cái gì đó như thế IFS=":" for i in $PATH; do echo $i; donenhưng nó dẫn đến lỗi cú pháp. Tôi luôn có thể làm điều gì đó như thế oldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS", nhưng tôi muốn biết liệu có cách nào tôi có thể làm cho các phép gán nội tuyến như vậy hoạt động cho các câu lệnh ghép như forvòng lặp không?

Trả lời

3 Quasímodo Aug 16 2020 at 21:12

forlà một từ dành riêng và như vậy tuân theo các quy tắc đặc biệt :

Các từ sau đây sẽ được coi là từ dành riêng:

! {} case do done elif else esac fi cho if in then cho đến khi

Việc nhận dạng này chỉ xảy ra khi không có ký tự nào được trích dẫn và khi từ được sử dụng như:

  • Từ đầu tiên của một lệnh

  • Từ đầu tiên sau một trong những từ dành riêng khác hơn là trường hợp , cho , hoặc trong

  • Từ thứ ba trong lệnh trường hợp (chỉ trong mới hợp lệ trong trường hợp này)

  • Từ thứ ba trong lệnh for (chỉ trongdo hợp lệ trong trường hợp này)

Nếu bạn cố gắng

IFS=":" for i in $PATH; do echo $i; done

, theo các quy tắc trên, đó không phải là một forvòng lặp, vì từ khóa không phải là từ đầu tiên của lệnh. Nhưng mục đích của bạn có thể đạt được với

IFS=: printf '%s\n' $PATH

$PATHtrải qua quá trình tách từ :như mong đợi và mỗi từ kết quả được in ra printf, theo sau là một dòng mới.


Bạn có thể quen với cách tiếp cận hợp lệ này:

while IFS= read -r line; do

whilelà từ đầu tiên của lệnh và việc IFSgán áp dụng cho read, vì vậy tất cả đều OK.