Bí danh và chức năng


17

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

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 trước khi thực hiện bất kỳ lệnh nào trên dòng đó. 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 ghép. Hậu quả là bí danh được xác định trong một hàm không có sẵn cho đến 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.

Hai câu "Bí danh được mở rộng khi đọc định nghĩa hàm, không phải khi hàm được thực thi" và "bí danh được định nghĩa trong hàm không khả dụng cho đến khi hàm đó được thực thi" dường như trái ngược với nhau.

Bạn có thể giải thích ý nghĩa của chúng tương ứng?


Câu hỏi hay! Tôi nghiêng một cái gì đó mới ngày hôm nay. Tôi đã học được 2 điều, thực tế: 1) thông tin này về việc mở rộng bí danh tại thời điểm hàm def được đọc và 2) tôi thực sự nên đọc kỹ hướng dẫn bash (mà tôi nghĩ tôi đã làm rồi, nhưng rõ ràng là không ^^ )
Olivier Dulac

4
Câu hỏi chính là, có ai nên sử dụng bí danh trong chế độ không tương tác? Đó là những chức năng dành cho, và các bí danh chỉ khiến cho kịch bản dễ bị lỗi hơn. Tôi thực sự không bao giờ cần thông tin ở trên, bởi vì tôi chỉ gặp phải bí danh trong .bashrccác tệp ở trên cùng.
orion

Câu trả lời:


29
  1. Các bí danh được mở rộng khi đọc định nghĩa hàm, không phải khi hàm được thực thi.

    $ echo "Con cáo nâu nhanh nhẹn nhảy qua con chó lười." > tài khoản của tôi
     
    $ bí danh myalias = mèo
     
    $ myfunc () {
    > myalias myfile
    >}
     
    $ myfunc
    The quick brown fox jumps over the lazy dog.
     
    $ bí danh myalias = "ls -l"
     
    $ myalias myfile
    -rw-r - r-- 1 myusername mygroup 45 Dec 13 07:07 myfile
     
    $ myfunc
    The quick brown fox jumps over the lazy dog.

    Mặc dù myfuncđã được xác định để gọi myaliasvà tôi đã xác định lại myalias, myfuncvẫn thực hiện định nghĩa ban đầu myalias. Bởi vì bí danh đã được mở rộng khi hàm được xác định. Trong thực tế, vỏ không còn nhớ rằng myfunccác cuộc gọi myalias; nó chỉ biết rằng myfuncgọi cat:

    $ loại myfunc
    myfunc là một chức năng
    myfunc ()
    {
    mèo của tôi
    }
  2. Các bí danh được định nghĩa trong một hàm không có sẵn cho đến khi hàm đó được thực thi.

    $ echo "Con cáo nâu nhanh nhẹn nhảy qua con chó lười." > tài khoản của tôi
     
    $ myfunc () {
    > bí danh myalias = mèo
    >}
     
    $ myalias myfile
    -bash: myalias: lệnh không tìm thấy
     
    $ myfunc
     
    $ myalias myfile
    The quick brown fox jumps over the lazy dog.

    Các myaliasbí danh là không có sẵn cho đến khi myfuncchức năng được thực thi. (Tôi tin rằng sẽ khá kỳ quặc nếu xác định hàm xác định bí danh là đủ để khiến bí danh được xác định.)


4
+1, câu trả lời tốt. Một "hệ quả" quan trọng đối với điều này là nếu một người có ý định xác định các hàm và bí danh trong một tập lệnh, tốt hơn nên đặt định nghĩa bí danh trước các định nghĩa hàm! (rõ ràng, bây giờ, đưa ra câu trả lời, nhưng tôi không biết điều này).
Olivier Dulac

Cảm ơn. Tôi nghĩ rằng một vấn đề cơ bản là sự khác biệt giữa việc chạy định nghĩa của hàm và gọi hàm. Cụ thể, những hoạt động shell nào được thực hiện trong khi chạy định nghĩa của hàm và trong khi gọi hàm tương ứng? Có bất kỳ hoạt động shell nào được thực hiện trong cả khi chạy định nghĩa của hàm và gọi hàm hoặc chạy định nghĩa của hàm và gọi hàm thực hiện tập hợp các thao tác shell không chồng chéo?
Tim

Chà, nó giống như sự khác biệt giữa chế tạo xe hơi và lái xe hơi. Hoặc mua một chiếc bánh sandwich và ăn một chiếc bánh sandwich. Tôi đã cung cấp một câu trả lời chi tiết hơn cho câu hỏi khác của bạn .
G-Man nói 'Tái lập Monica'

Cảm ơn. Sau khi đọc lại trích dẫn từ hướng dẫn bash và trả lời của bạn, tôi bối rối về ý nghĩa của việc thực hiện một chức năng. Nó có nghĩa là thực hiện định nghĩa của một chức năng, hoặc gọi một chức năng? Xem unix.stackexchange.com/q/384209/674
Tim

1

Tôi cần câu trả lời được nêu trong câu đầu tiên khi tôi thử bên dưới đoạn trích trong.bashrc .

alias ls='\ls -F --color=auto --show-control-chars'
alias ll='ls -ahl'
function lf_macro() {
    local CMD=${1:-ls} DIR=${2:-.};
    $CMD $(find $DIR -maxdepth 1 -type f);
}
function lf() { lf_macro ll "$1"; }
function lsf() { lf_macro ls "$1"; }     # list all file, no directories

Sau đó unalias -a; source ~/.bashrc, tôi cố gắng thực hiện lflsf,

$ lf
-bash: ll: command not found

$ lsf
./file1 ./file2 ./script.sh ...     # no color, no control-chars

$ ls $(find -maxdepth 1 -type f)
./file1 ./file2 ./script.sh* ...

có vẻ như rõ ràng rằng các bí danh được mở rộng ở định nghĩa hàm, không phải thực thi hàm, vì :

  • Khi tôi thực thi lf, lỗi -bash: ll: command not found
  • khi tôi thực thi lsf, /usr/bin/lsđược sử dụng, không phải dạng bí danh, không tô sáng màu và không có ký tự điều khiển sau tệp thực thi.
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.