Trong một số shell (bao gồm bash
):
IFS=: command eval 'p=($PATH)'
(với bash
, bạn có thể bỏ qua phần command
mô phỏng sh / POSIX) nếu không. Nhưng hãy cẩn thận khi sử dụng các biến không được trích dẫn, nhìn chung bạn cũng cần set -f
và không có phạm vi cục bộ cho điều đó trong hầu hết các shell.
Với zsh, bạn có thể làm:
(){ local IFS=:; p=($=PATH); }
$=PATH
là để buộc chia tách từ mà không được thực hiện theo mặc định zsh
(việc mở rộng khi mở rộng biến cũng không được thực hiện nên bạn không cần set -f
trừ khi trong mô phỏng sh).
(){...}
(hoặc function {...}
) được gọi là các hàm ẩn danh và thường được sử dụng để đặt phạm vi cục bộ. với các shell khác hỗ trợ phạm vi cục bộ trong các hàm, bạn có thể làm điều gì đó tương tự với:
e() { eval "$@"; }
e 'local IFS=:; p=($PATH)'
Để triển khai phạm vi cục bộ cho các biến và tùy chọn trong shell POSIX, bạn cũng có thể sử dụng các hàm được cung cấp tại https://github.com/stephane-chazelas/misc-scripts/blob/master/locvar.sh . Sau đó, bạn có thể sử dụng nó như:
. /path/to/locvar.sh
var=3,2,2
call eval 'locvar IFS; locopt -f; IFS=,; set -- $var; a=$1 b=$2 c=$3'
(bằng cách này, không hợp lệ để phân chia $PATH
theo cách đó, ngoại trừ zsh
như trong các shell khác, IFS là dấu phân cách trường, không phải là dấu tách trường).
IFS=$'\n' a=($str)
Chỉ là hai bài tập, hết lần này đến lần khác a=1 b=2
.
Một lưu ý giải thích về var=value cmd
:
Trong:
var=value cmd arg
Shell thực hiện /path/to/cmd
trong một quy trình mới và thông qua cmd
và arg
trong argv[]
và var=value
trong envp[]
. Đó không thực sự là một phép gán biến, nhưng nhiều biến môi trường hơn cho lệnh được thực thi . Trong vỏ Bourne hoặc Korn, với set -k
, bạn thậm chí có thể viết nó cmd var=value arg
.
Bây giờ, điều đó không áp dụng cho các nội dung hoặc hàm không được thực thi . Trong shell Bourne var=value some-builtin
, var
cuối cùng , được thiết lập sau đó, giống như với var=value
một mình. Điều đó có nghĩa là, ví dụ, hành vi của var=value echo foo
(không hữu ích) thay đổi tùy thuộc vào việc có echo
được dựng sẵn hay không.
POSIX và / hoặc ksh
thay đổi rằng trong đó hành vi của Bourne chỉ xảy ra đối với một loại nội dung được gọi là nội dung đặc biệt . eval
là một nội dung đặc biệt, read
không. Đối với nội dung không đặc biệt, chỉ var=value builtin
thiết lập var
cho việc thực thi nội dung khiến nó hoạt động tương tự như khi một lệnh bên ngoài đang được chạy.
Các command
lệnh có thể được sử dụng để loại bỏ các đặc biệt thuộc tính của những builtins đặc biệt . Điều mà POSIX đã bỏ qua là đối với các nội trang eval
và .
nội dung, điều đó có nghĩa là các shell sẽ phải thực hiện một ngăn xếp biến (mặc dù nó không chỉ định các lệnh local
hoặc typeset
giới hạn phạm vi), bởi vì bạn có thể làm:
a=0; a=1 command eval 'a=2 command eval echo \$a; echo $a'; echo $a
Hoặc thậm chí:
a=1 command eval myfunction
với myfunction
chức năng sử dụng hoặc cài đặt $a
và có khả năng gọi command eval
.
Đó thực sự là một sự bỏ qua bởi vì ksh
(mà thông số kỹ thuật chủ yếu dựa trên) đã không thực hiện nó (và AT & T ksh
và zsh
vẫn không), nhưng ngày nay, ngoại trừ hai, hầu hết các shell đều thực hiện nó. Hành vi khác nhau giữa các vỏ mặc dù trong những thứ như:
a=0; a=1 command eval a=2; echo "$a"
Tuy nhiên. Sử dụng các local
shell hỗ trợ nó là một cách đáng tin cậy hơn để thực hiện phạm vi cục bộ.
IFS=: command eval …
đặtIFS
trong khoảng thời gianeval
, như được ủy quyền bởi POSIX, trong dấu gạch ngang, pdksh và bash, nhưng không phải trong ksh 93u. Thật bất thường khi thấy ksh là người không tuân thủ một cách kỳ quặc.