Cách đơn giản nhất để kiểm tra xem một biến shell có được xuất không?


20

Đối với một số phiên shell tôi muốn có thể in cờ cảnh báo nếu biến shell không được đặt và xuất.

Khá đơn giản để làm một cái gì đó như thế này để in "Lỗi" trong lời nhắc nếu SET_MEkhông được đặt hoặc null.

test_var () { test -z "$1" && echo Error; }
PS1='$(test_var "$SET_ME") \$ '

Tuy nhiên điều này không gắn cờ nếu tôi đặt SET_MEmà không xuất nó, đây là một lỗi mà tôi muốn có thể phát hiện ra. Thiếu một cái gì đó như $(bash -c 'test -z "$SET_ME" && echo Error;')hoặc lấy đầu ra của export, có một kiểm tra đơn giản mà tôi có thể làm để kiểm tra xem SET_MEđã được xuất chưa?

Một giải pháp không chỉ POSIX, bash là hoàn toàn chấp nhận được.

Câu trả lời:


11

Sử dụng declarelệnh và toán tử khớp biểu thức chính quy:

test_var () {
    # $1 - name of a shell variable
    var=$1
    [[ -z "${!var}" ]] && echo Error
    [[ $(declare -p $1)  =~ ^declare\ -[aAilrtu]*x[aAilrtu]*\  ]] || echo Error
}

Tôi nghĩ rằng đây là những gì tôi đang tìm kiếm. Về lý thuyết, re có thể cần phải linh hoạt hơn, ví dụ nếu tôi có biến xuất chỉ đọc, nhưng trong thực tế tôi không bao giờ sử dụng các typesetthuộc tính khác .
CB Bailey

Điểm tốt. Tôi sẽ sửa nó cho hậu thế.
chepner

Có vẻ như việc cố gắng trích dẫn biểu thức chính quy ngăn nó hoạt động như một biểu thức chính quy trong bash> = 3.2.
CB Bailey

Ngoài ra, có một sự không nhất quán, -z "$1"giả sử tôi chuyển giá trị của một biến sang test_var(như tôi) trong khi declare -pmong đợi tên của nó. Tôi đã đưa ra thử nghiệm này trong đó có tên của một biến shell : test_exported_notnull () { re='^declare -\w*x'; [[ -n $(eval echo \$$1) ]] && [[ $(declare -p "$1") =~ $re ]]; }.
CB Bailey

Để tránh eval, chỉ cần thêm dòng đầu tiên này : var=$1, sau đó sử dụng [[ -z "${!var}" ]] && echo Error.
chepner

4

Tôi biết câu hỏi đã 3 tuổi, tuy nhiên người ta có thể tìm thấy giải pháp sau đơn giản hơn:

[ "$(bash -c 'echo ${variable}')" ]

câu trả lời, nếu biến được xuất và có giá trị không trống.


4

Trong Bash 4.4 trở lên , bạn có thể sử dụng ${parameter@a} mở rộng tham số shell để lấy danh sách các thuộc tính về một tham số, bao gồm cả nếu nó được xuất.

Đây là một hàm đơn giản minh họa ${parameter@a}, nó sẽ cho bạn biết nếu một biến đã cho được xuất ra, với tên của nó:

function is_exported {
    local name="$1"
    if [[ "${!name@a}" == *x* ]]; then
        echo "Yes - '$name' is exported."
    else
        echo "No - '$name' is not exported."
    fi
}

Ví dụ sử dụng:

$ is_exported PATH
Yes - 'PATH' is exported.
$ foo=1 is_exported foo
Yes - 'abc' is exported.
$ bar=1; is_exported bar
No - 'abc' is not exported.
$ export baz=1; is_exported baz
Yes - 'baz' is exported.
$ export -n baz; is_exported baz
No - 'baz' is not exported.
$ declare -x qux=3; is_exported qux
Yes - 'qux' is exported.

Làm thế nào nó hoạt động:

Định dạng được trả về ${parameter@a}là một ký tự cho mỗi thuộc tính, với ý nghĩa của từng ký tự thuộc tính đến từ các tùy chọn tương ứng từ lệnh khai báo - trong trường hợp này, chúng tôi muốn tìm kiếm x- đã xuất.


Câu trả lời tốt nhất nếu bạn đang sử dụng Bash 4.4 hoặc mới hơn!
Andy

3

Bạn có thể sử dụng compgenvới -Xtùy chọn của nó để xác định xem một biến có được xuất không:

compgen -e -X "!$MAY_BE_EXPORTED_VARIABLE"

Ví dụ:

$ NOT_EXPORTED="xxx"
$ compgen -e -X '!SHELL'
SHELL
$ compgen -e -X '!NOT_EXPORTED'
$ echo $?
1

Câu trả lời tương thích tốt nhất! Chậm hơn hai lần so với giải pháp $ {tham số @ a}, nhưng tương thích hơn nhiều đối với các trường hợp bash 3.2
Andy

2

Nếu tôi từ bỏ bản thân để sử dụng exportgrep, thử nghiệm đơn giản nhất có lẽ là một cái gì đó như thế này.

export | grep -Eq '^declare -x SET_ME='

hoặc nếu tôi cũng muốn không null:

export | grep -Eq '^declare -x SET_ME=".+"'

1
POSIX 7 nói rằng exportkhông xác định và định nghĩa một định dạng chính xác cho export -ptương tự như bash exportnhưng khác nhau. Nhưng bash dường như bỏ qua POSIX và sử dụng định dạng tương tự như exportcho export -p!
Ciro Santilli 心 心 事件

1

Các exportlệnh, do không có tham số, đưa ra một danh sách các tên xuất khẩu trong môi trường hiện tại:

$ FOO1=test
$ FOO2=test
$ export | grep FOO
$ export FOO2
$ export | grep FOO
declare -x FOO2="test"

Một số cắt và quyến rũ được loại bỏ lông tơ:

export | cut -d' ' -f 3- | sed s/=.*//

Có danh sách xuất khẩu của bạn, sẵn sàng để xử lý thêm.


1
Điều này không hiệu quả nhưng tôi đã hy vọng có một câu trả lời nhẹ hơn với ít nhánh hơn ngụ ý (do đó "Short of [...] grepping đầu ra của export") vì việc sử dụng theo kế hoạch của tôi là trong lời nhắc của tôi.
CB Bailey

@CharlesBailey: Tôi hiểu rồi. Tôi đã đến đây bằng cách tìm kiếm trang bash cho export, và đây là điều duy nhất tôi nghĩ ra. Không có sự giúp đỡ từ vỏ thoát. Các exportlà BUILTIN dù sao, nhưng tôi nghi ngờ bạn có thể tránh được grep.
DevSolar

1

Phương pháp đơn giản nhất hiện tại tôi có thể nghĩ ra:

[ bash -c ': ${v1?}' 2>/dev/null ]
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.