Chạy các lệnh được lưu trữ trong các biến shell


7

Các tác phẩm sau trong shell của tôi (zsh):

> FOO='ls'
> $FOO
file1 file2

nhưng sau đây không:

> FOO='emacs -nw'
> $FOO
zsh: command not found: emacs -nw

mặc dù việc gọi emacs -nwtrực tiếp mở Emacs hoàn toàn tốt.

Tại sao?


1
Các backticks trong lệnh thứ 2 của bạn chỉ là lỗi OCR hay bạn có thực sự sử dụng chúng trong tập lệnh của mình không?
thử-bắt-cuối cùng

1
Cũng như một nhận xét: Trong bash đó sẽ làm việc.
Hauke ​​Laging 28/12/14

1
@HaukeLaging, sẽ hoạt động trừ khi IFS được sửa đổi.
Stéphane Chazelas

3
@ thử-bắt-cuối cùng Nhưng trong trường hợp này, thông báo lỗi cho thấy anh ta đã sử dụng dấu ngoặc kép, không phải backticks.
Hauke ​​Laging 28/12/14

3
@HaukeLaging, không có zshhành vi như bạn mong đợi. Khi bạn gõ $cmd, nó sẽ chạy lệnh có tên được lưu trữ $cmd. bash(và hầu hết các Bourne khác như shell) gọi toán tử split + global trên các biến không được trích dẫn, đã zsh sửa lỗi đó.
Stéphane Chazelas

Câu trả lời:


8

Bởi vì không có lệnh nào được gọi emacs -nw. Có một lệnh được gọi emacsmà bạn có thể vượt qua một -nwtùy chọn.

Để lưu trữ các lệnh, bạn thường sử dụng các hàm :

foo() emacs -nw "$@"
foo ...

Để lưu trữ một số đối số, bạn thường sử dụng mảng:

foo=(emacs -nw)
$foo ...

Để lưu trữ một chuỗi chứa một số từ được phân tách bằng dấu cách và phân tách nó trên khoảng trắng, bạn có thể thực hiện:

foo='emacs -nw'
${(s: :)foo} ...

Bạn có thể dựa vào phân tách từ được thực hiện trên IFS (IFS chứa khoảng trắng, tab, dòng mới và nul theo mặc định):

foo='emacs -nw'
$=foo ...

Bạn có nhận thấy backticks trong lệnh thứ 2 trong OP không?
thử bắt cuối cùng

Cảm ơn @Stephane, điều này rất hữu ích, như thường lệ. Bây giờ tôi đang hy vọng có ý nghĩa của câu trả lời này trong bối cảnh của câu hỏi khác này . Để làm như vậy, tôi đã thử >my_wrapper.sh "some text" (date '+%d')nơi my_wrapperđược cho là sẽ gọi lệnh date '+%d', nhưng nó không hoạt động.
Amelio Vazquez-Reina

@ user815423426 - có thể xem câu trả lời của Stéphane ở đây có thể. Bạn cũng có thể liếc nhìn tôi. Vấn đề bạn gặp phải là do thứ tự đánh giá của trình bao trong khi phân tích cú pháp lệnh của bạn và (subshell)- trình phân tích cú pháp cần đọc cùng lúc nó nhận ra sự mở rộng biến đổi - điều này rõ ràng không thể xảy ra nếu các (parens )nằm trong phần mở rộng. Bạn cần eval- hoặc và alias- dưới hình thức này hay hình thức khác.
mikeerv

Không bao giờ vấn đề xảy ra datelà do thực tế crontabđòi hỏi phải trốn thoát %dnhư @Gilles đã đề cập ở đây
Amelio Vazquez-Reina

3

Đối với độc giả trong tương lai, cần đề cập rằng cách làm "tiêu chuẩn" để thực hiện điều đó là evaluate các đối số được lưu trữ trong biến:

eval "$foo"

Người ta cũng có thể đánh giá biểu thức với sự thay thế lệnh:

$(expr "$foo")

echobiến ed (hoặc được in khác) cũng hoạt động:

$(echo "$foo")

Các phương pháp này hoạt động tốt ít nhất trong zshbash.

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.