bí danh bash không mở rộng ngay cả với shopt extend_aliases


8

Tôi muốn chạy một bí danh trong một bash -ccấu trúc.

Các bashtay nói:

Bí danh không được mở rộng khi shell không tương tác, trừ khi expand_aliasestùy chọn shell được đặt bằng cách sử dụngshopt

Trong ví dụ này, tại sao bí danh hikhông được tìm thấy khi cài đặt expand_aliasesrõ ràng?

% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases  on
bash: hi: command not found

Tôi đang chạy GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).

Bối cảnh: Tôi muốn có thể chạy bí danh ở mức ưu tiên nhàn rỗi, ví dụ: tập lệnh chứa:

#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"

Tôi muốn tránh sử dụng bash -ivì tôi không muốn .bashrcđọc.


3
Đoạn văn ngay sau câu lệnh được trích dẫn từ hướng dẫn Bash dường như bao gồm điều này: '... Bí danh được mở rộng khi một lệnh được đọc, không phải khi nó được thực thi. Do đó, một định nghĩa bí danh xuất hiện trên cùng một dòng với một lệnh khác không có hiệu lực cho đến khi dòng đầu vào tiếp theo được đọc. Các lệnh theo định nghĩa bí danh trên dòng đó không bị ảnh hưởng bởi bí danh mới .... '
Haxiel

Như trong hầu hết các trường hợp, bạn nên xem xét sử dụng hàm shell thay vì bí danh ở đây. bash -c "hi () { echo hello; }; hi"đầu ra hello.
chepner

Câu trả lời:


16

Nó dường như không hoạt động nếu bạn đặt bí danh trên cùng một dòng như nó được sử dụng. Có lẽ phải làm gì đó với cách các bí danh được mở rộng thực sự sớm trong quá trình xử lý dòng lệnh, trước giai đoạn phân tích cú pháp thực tế. Trên một vỏ tương tác:

$ alias foo
bash: alias: foo: not found
$ alias foo='echo foo'; foo         # 2 
bash: foo: command not found
$ alias foo='echo bar'; foo         # 3
foo
$ foo
bar

Lưu ý cách bí danh được sử dụng là trễ một dòng: trên lệnh thứ hai, nó không tìm thấy bí danh vừa được đặt và trên lệnh thứ ba, nó sử dụng một bí danh đã được đặt trước đó.

Vì vậy, nó hoạt động nếu chúng ta đặt một dòng mới trong -cchuỗi:

$ bash -c $'shopt -s expand_aliases; alias foo="echo foo";\n foo'
foo

(Bạn cũng có thể sử dụng bash -O expand_aliases -c ...thay vì sử dụng shopttrong tập lệnh, không phải là nó giúp với dòng mới.)

Ngoài ra, bạn có thể sử dụng hàm shell thay vì bí danh, chúng cũng tốt hơn theo nhiều cách khác:

$ bash -c 'foo() { echo foo; }; foo'
foo

14

Biến nhận xét của tôi thành một câu trả lời, theo đề xuất của ilkkachu.

Hướng dẫn Bash (được liên kết đến trong câu hỏi) không cung cấp giải thích về cách xử lý các bí danh khi có một định nghĩa bí danh và một lệnh trên cùng một dòng.

Trích dẫn (hơi định dạng cho rõ ràng):

Các quy tắc liên quan đến định nghĩa và sử dụng bí danh có phần khó hiểu. Bash luôn đọc ít nhất một dòng đầu vào hoàn chỉnh và tất cả các dòng tạo thành một lệnh ghép, trước khi thực hiện bất kỳ lệnh nào trên dòng đó hoặc lệnh ghép.

Các bí danh được mở rộng khi một lệnh được đọc, không phải khi nó được thực thi. Do đó, một định nghĩa bí danh xuất hiện trên cùng một dòng với một lệnh khác không có hiệu lực cho đến khi dòng đầu vào tiếp theo được đọc. Các lệnh theo định nghĩa bí danh trên dòng đó không bị ảnh hưởng bởi bí danh mới.

Hành vi này cũng là một vấn đề khi các chức năng được thực thi. Các bí danh được mở rộng khi một định nghĩa hàm được đọc, không phải khi hàm được thực thi, bởi vì một định nghĩa hàm tự nó là một lệnh. Kết quả là, các bí danh được xác định trong một hàm không có sẵn cho đến sau khi hàm đó được thực thi.

Để an toàn, luôn đặt các định nghĩa bí danh trên một dòng riêng biệt và không sử dụng bí danh trong các lệnh ghép.

Câu trả lời của ilkkachu cung cấp nhiều giải pháp khả thi cho vấn đề này.


FWIW, tôi đã thấy bình luận cuối cùng của bạn nhưng không có thời gian để trả lời. Nó không phải là một điều xấu cho câu trả lời để bổ sung cho người khác, và biết rằng nó thực sự được ghi lại theo cách đó hữu ích. Vì vậy, cảm ơn bạn đã viết nó lên, bây giờ tôi có thể nâng cấp nó. :)
ilkkachu
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.