chọn từ $ 0 đến BASH_SOURCE


117

Làm thế nào để một người lựa chọn giữa "$0""${BASH_SOURCE[0]}"

Mô tả này từ GNU không giúp tôi nhiều.

    BASH_SOURCE

 An array variable whose members are the source filenames where the
 corresponding shell function names in the FUNCNAME array variable are
 defined. The shell function ${FUNCNAME[$i]} is defined in the file
 ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}

BASH_SOURCEđã được thêm vào lúc bash-3.0-alpha. Bạn có thể không có, tùy thuộc vào chế độ kiểm tra của bạn. Tôi thấy nó bị thiếu trên cả Solaris và OS X. Ngoài ra, hãy xem return: chỉ có thể trả về từ một hàm hoặc tập lệnh có nguồn gốc trên U & L.SE.
jww

Câu trả lời:


174

Lưu ý: Để biết giải pháp tương thích với POSIX, hãy xem câu trả lời này .

${BASH_SOURCE[0]}(hoặc đơn giản hơn, $BASH_SOURCE[1] ) chứa đường dẫn (có khả năng tương đối) của tập lệnh chứa trong tất cả các trường hợp gọi, đặc biệt là khi tập lệnh được lấy nguồn , điều này không đúng với $0.

Hơn nữa, như Charles Duffy đã chỉ ra, người gọi $0có thể đặt thành một giá trị tùy ý .
Mặt khác, $BASH_SOURCE thể để trống, nếu không có tệp được đặt tên nào liên quan; ví dụ:
echo 'echo "[$BASH_SOURCE]"' | bash

Ví dụ sau đây minh họa điều này:

Tập lệnh foo:

#!/bin/bash
echo "[$0] vs. [${BASH_SOURCE[0]}]"

$ bash ./foo
[./foo] vs. [./foo]

$ ./foo
[./foo] vs. [./foo]

$ . ./foo
[bash] vs. [./foo]

$0là một phần của đặc tả trình bao POSIX, trong khi BASH_SOURCE, như tên cho thấy, là dành riêng cho Bash.


[1] Đọc tùy chọn: ${BASH_SOURCE[0]}vs.$BASH_SOURCE :

Bash cho phép bạn tham chiếu phần tử 0của một biến mảng bằng cách sử dụng ký hiệu vô hướng : thay vì viết ${arr[0]}, bạn có thể viết$arr ; nói cách khác: nếu bạn tham chiếu biến như thể nó là một đại lượng vô hướng , bạn sẽ nhận được phần tử ở chỉ mục 0.

Sử dụng tính năng này che khuất thực tế rằng $arr là một mảng, đó là lý do tại sao mã shell phổ biến linter shellcheck.net đưa ra cảnh báo sau (tính đến thời điểm viết bài này):

SC2128: Mở rộng mảng không có chỉ mục chỉ đưa ra phần tử đầu tiên.

Một lưu ý nhỏ: Mặc dù cảnh báo này hữu ích, nhưng nó có thể chính xác hơn, vì bạn sẽ không nhất thiết phải nhận được phần tử đầu tiên : Đó là phần tử cụ thể tại chỉ mục 0được trả về, vì vậy nếu phần tử đầu tiên có chỉ số cao hơn - thì là có thể trong Bash - bạn sẽ nhận được chuỗi trống; thử 'a[1]='hi'; echo "$a"'.
(Ngược lại,zsh , bao giờ những phản bội, thực sự không trả về phần tử đầu tiên, bất kể chỉ mục của nó).

Bạn có thể chọn để tránh tính năng này do tính không rõ ràng của nó, nhưng nó hoạt động có thể đoán trước được và nói một cách thực dụng, bạn sẽ hiếm khi cần truy cập vào các chỉ số khác ngoài 0biến mảng ${BASH_SOURCE[@]}.


vì vậy $ BASH_SOURCE chung chung hơn và hoạt động trong nhiều trường hợp hơn?
Alexander Mills

2
@AlexanderMills Có, nếu bạn đang sử dụng Bash, $BASH_SOURCElà lựa chọn tốt hơn.
mklement0

18

Những đoạn mã này có thể giúp minh họa. Tập lệnh bên ngoài gọi tập lệnh giữa, tập lệnh này gọi tập lệnh bên trong:

$ cat outer.sh
#!/usr/bin/env bash
./middle.sh
$ cat middle.sh
#!/usr/bin/env bash
./inner.sh
$ cat inner.sh
#!/usr/bin/env bash
echo "\$0 = '$0'"
echo "\${BASH_SOURCE[0]} = '${BASH_SOURCE[0]}'"
echo "\${BASH_SOURCE[1]} = '${BASH_SOURCE[1]}'"
echo "\${BASH_SOURCE[2]} = '${BASH_SOURCE[2]}'"
$ ./outer.sh
$0 = './inner.sh'
$BASH_SOURCE[0] = './inner.sh'
$BASH_SOURCE[1] = ''
$BASH_SOURCE[2] = ''

Tuy nhiên, nếu chúng ta thay đổi các lệnh gọi script thành các sourcecâu lệnh:

$ cat outer.sh
#!/usr/bin/env bash
source ./middle.sh
$ cat middle.sh
#!/usr/bin/env bash
source ./inner.sh
$ cat inner.sh
#!/usr/bin/env bash
echo "\$0 = '$0'"
echo "\${BASH_SOURCE[0]} = '${BASH_SOURCE[0]}'"
echo "\${BASH_SOURCE[1]} = '${BASH_SOURCE[1]}'"
echo "\${BASH_SOURCE[2]} = '${BASH_SOURCE[2]}'"
$ ./outer.sh
$0 = './outer.sh'
$BASH_SOURCE[0] = './inner.sh'
$BASH_SOURCE[1] = './middle.sh'
$BASH_SOURCE[2] = './outer.sh'

1

Đối với tính di động, hãy sử dụng ${BASH_SOURCE[0]}khi nó được xác định, và $0nếu không. Điều đó cho

${BASH_SOURCE[0]:-$0}

Đáng chú ý, nói rằng zsh, $ 0 chứa đúng đường dẫn tệp ngay cả khi tập lệnh là sourced.

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.