Bash Alias ​​- Precedence / Shadowing (/ ẩn / thất bại)

Aug 17 2020

Tôi có một số thiết lập bí danh (theo thứ tự này) trong .bashrc:

alias ls="lsc"
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'

Xác nhận chúng với aliassau khi tìm nguồn cung ứng:

alias ls='lsc'
alias lsc='ls -Flatr --color=always'
alias lscR='ls -FlatrR --color=always'

Tôi có thể chạy bí danh mới lsvừa tốt, và nó xâu chuỗi đến bí danh lsc, rồi thực thi lệnh được liên kết với bí danh lsc. Tôi cũng có thể chạy lscRvà nó hoạt động như mong đợi.

Nếu tôi cố gắng lsctự chạy , tôi nhận được:

$ lsc
lsc: command not found

Bất kỳ ý tưởng nào tại sao trình bao dường như ẩn / ẩn bí danh lsc trong trường hợp này? (Tôi nhận ra rằng thật vô nghĩa khi chạy 'lsc' khi tôi chỉ có thể chạy 'ls' để nhận được kết quả tương tự ở đây, nhưng tôi đang cố gắng hiểu hành vi của trình bao trong trường hợp này).

CHỈNH SỬA: Cách giải quyết bên dưới cho hành vi shell (bash) được cung cấp trong câu trả lời câu hỏi.

Một số câu trả lời thực sự hữu ích đã được cung cấp cho câu hỏi ban đầu. Để làm ngắn mạch hành vi mở rộng được giải thích trong các câu trả lời, dường như có ít nhất hai cách để ngăn bí danh thứ hai cố gắng mở rộng lệnh mà bạn đã có bí danh. Ví dụ: nếu bạn có alias cmd='cmd --stuff'đang ghi đè một lệnh gốc được gọi cmd, bạn có thể ngăn bí danh 'cmd' được sử dụng thay cho cmdbí danh gốc trong các bí danh khác, bằng cách:

(cảm ơn nhận xét của wjandrea cho cách tiếp cận đầu tiên này)

  1. tiền tố cmdbằng 'lệnh' trong bí danh khác, ví dụ:alias other-cmd-alias='command cmd --other-stuff'

hoặc là,

  1. Tương tự, bạn có thể thoát các bí danh (như bạn cũng có thể làm trên dòng lệnh), trong các bí danh khác bằng cách đặt tiền tố bằng dấu gạch chéo ngược '', ví dụ alias other-cmd-alias='\cmd --other-stuff'.

Trả lời

13 John1024 Aug 17 2020 at 11:58

Bash không cho phép các bí danh chứa bí danh nhưng nó có các biện pháp bảo vệ tích hợp chống lại các vòng lặp vô hạn. Trong trường hợp của bạn, khi bạn nhập lsc, bash trước tiên sẽ mở rộng bí danh thành:

ls -Flatr --color=always

lscũng là một bí danh, bash mở rộng nó thành:

lsc -Flatr --color=always

lsclà một bí danh nhưng, khá hợp lý, bash từ chối mở rộng nó lần thứ hai . Nếu có một chương trình được đặt tên lsc, bash sẽ chạy nó. Nhưng, không có và đó là lý do tại sao bạn nhận được command not found.

Phụ lục

Khi lscRchạy thì khác . lscRmở rộng thành:

ls -FlatrR --color=always

lslà một bí danh, điều này mở rộng thành:

lsc -FlatrR --color=always

lsclà một bí danh, điều này mở rộng thành:

ls -Flatr --color=always -FlatrR --color=always

lsđã được mở rộng một lần nên bash từ chối mở rộng lần thứ hai . Vì một lệnh thực được gọi là lstồn tại, nó sẽ được chạy.

Lịch sử

Như đã lưu ý bởi Schily trong các bình luận, bash đã mượn khái niệm không mở rộng bí danh lần thứ hai từ ksh .

Qua một bên

Bí danh rất hữu ích nhưng không mạnh lắm. Nếu bạn muốn làm điều gì đó phức tạp với một bí danh, chẳng hạn như thay thế đối số, đừng; thay vào đó sử dụng một hàm shell.

6 muru Aug 17 2020 at 12:00

Từ hướng dẫn sử dụng bash :

Từ đầu tiên của văn bản thay thế được kiểm tra bí danh, nhưng một từ giống với bí danh đang được mở rộng sẽ không được mở rộng lần thứ hai. Điều này có nghĩa là một người có thể đặt bí danh lslà " ls -F", và Bash không cố gắng mở rộng đệ quy văn bản thay thế.

Trong lsbí danh, lsđược mở rộng đến lscrồi lại đến ls -Flatr --color=always, và ở đó, việc mở rộng bí danh dừng lại, vì lsban đầu đã được mở rộng. Vì vậy, lệnh chạy tốt, lshiện đang được giải quyết thành lệnh bên ngoài.

Trong lscbí danh, lscđược mở rộng thành ls -Flatr --color=always, và sau đó lshiện được mở rộng đến lscở đó, việc mở rộng bí danh dừng lại, kể từ khi lscđược mở rộng ban đầu. Vì vậy, lệnh không thành công, vì bash không biết bất kỳ lệnh nào khác lsc.