Câu hỏi Làm cách nào để xác định xem biến bash có trống không?


Cách tốt nhất để xác định xem một biến trong bash có trống không ("") không?

Tôi đã nghe nói rằng tôi nên làm if [ "x$variable" = "x" ]

Đó có phải chính xác đường? (phải có một cái gì đó đơn giản hơn)


719
2018-05-12 17:54


gốc




Các câu trả lời:


Điều này sẽ trả về true nếu một biến không được đặt hoặc được đặt thành chuỗi rỗng ("").

if [ -z "$VAR" ];

980
2018-05-12 18:06



Điều đó có bao gồm nếu biến IS SET thành giá trị "" không? - Brent
Có nó không ... "-z" kiểm tra cho một chuỗi không có độ dài. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
nghịch đảo của -z Là -n  if [ -n "$VAR" ]; - Felipe Alvarez
Dấu ngoặc kép đảm bảo rằng biến không bị chia nhỏ. Đơn giản $var trên một dòng lệnh sẽ được phân chia bởi khoảng trống của nó thành một danh sách các tham số, trong khi "$var" sẽ luôn là chỉ một tham số. Việc trích dẫn các biến thường là một cách thực hành tốt và ngăn bạn không bị vấp phải các tên tập tin có chứa khoảng trắng (trong số những thứ khác). Ví dụ: sau khi thực hiện a="x --help", thử cat $a - nó sẽ cung cấp cho bạn trang trợ giúp cho cat. Vậy hãy thử đi cat "$a" - nó sẽ (thường) nói cat: x --help: No such file or directory. Trong ngắn hạn, báo giá sớm và báo giá thường xuyên và bạn sẽ gần như không bao giờ hối tiếc. - Score_Under


Trong Bash, khi bạn không quan tâm đến tính di động đối với các shell không hỗ trợ nó, bạn nên luôn sử dụng cú pháp ngoặc kép:

Bất kỳ điều nào sau đây:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

Trong Bash, sử dụng dấu ngoặc vuông kép, dấu ngoặc kép là không cần thiết. Bạn có thể đơn giản hóa thử nghiệm cho một biến làm chứa một giá trị để:

if [[ $variable ]]

Cú pháp này tương thích với ksh (ít nhất là ksh93). Nó không hoạt động trong các phiên bản POSIX hoặc Bourne thuần túy như sh hoặc dấu gạch ngang.

Xem câu trả lời của tôi ở đây và BashFAQ / 031 để biết thêm thông tin về sự khác biệt giữa dấu ngoặc vuông đơn và đôi.

Bạn có thể kiểm tra xem một biến cụ thể không được đặt (như khác với một chuỗi rỗng):

if [[ -z ${variable+x} ]]

trong đó "x" là tùy ý.

Nếu bạn muốn biết liệu một biến có null hay không không được đặt:

if [[ -z $variable && ${variable+x} ]]

227
2018-02-25 03:37



Cái đó if [[ $variable ]] làm việc tốt cho tôi, và thậm chí không cần set -u được yêu cầu bởi một trong các giải pháp được đề xuất khác. - Teemu Leisti
Tôi nghĩ điều này tốt hơn câu trả lời được chấp nhận. - qed
Tại sao bạn đề xuất một tính năng không di động khi làm như vậy sẽ không mang lại lợi ích gì? - Alastair Irvine
@AlastairIrvine: Tôi đề cập đến tính di động trong câu đầu tiên của câu trả lời của tôi, tiêu đề câu hỏi và nội dung chứa từ "Bash" và câu hỏi được gắn thẻ bashvà cấu trúc khung đôi cung cấp lợi thế rõ ràng bằng nhiều cách. Và tôi không khuyên bạn nên trộn phong cách khung vì lý do nhất quán và bảo trì. Nếu bạn cần tính di động mẫu số chung tối đa, thấp nhất, hãy sử dụng sh thay vì Bash. Nếu bạn cần các khả năng tăng lên mà nó cung cấp, hãy sử dụng Bash và sử dụng nó đầy đủ. - Dennis Williamson
@BrunoBronosky: Tôi đã hoàn nguyên bản chỉnh sửa. Không có yêu cầu cho ; cuối cùng. Các then có thể ở trên dòng tiếp theo mà không có dấu chấm phẩy nào cả. - Dennis Williamson


Một biến trong bash (và bất kỳ shell tương thích POSIX nào) có thể thuộc một trong ba trạng thái:

  • bỏ đặt
  • đặt thành chuỗi rỗng
  • đặt thành chuỗi không trống

Hầu hết thời gian bạn chỉ cần biết nếu biến được đặt thành chuỗi không trống, nhưng đôi khi điều quan trọng là phải phân biệt giữa bỏ đặt và đặt thành chuỗi rỗng.

Sau đây là ví dụ về cách bạn có thể kiểm tra các khả năng khác nhau, và nó hoạt động trong bash hoặc bất kỳ vỏ tương thích POSIX nào:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

Đây là điều tương tự nhưng ở dạng bảng tiện dụng:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

Các ${VAR+foo} cấu trúc mở rộng thành chuỗi rỗng nếu VAR chưa được đặt hoặc foo nếu VAR được đặt thành bất kỳ thứ gì (bao gồm chuỗi trống).

Các ${VAR-foo} xây dựng mở rộng đến giá trị của VAR nếu được đặt (bao gồm đặt thành chuỗi rỗng) và foo nếu bỏ đặt. Điều này hữu ích khi cung cấp mặc định do người dùng ghi đè (ví dụ: ${COLOR-red} nói để sử dụng red trừ khi biến COLOR đã được đặt thành thứ gì đó).

Lý do tại sao [ x"${VAR}" = x ] thường được khuyến khích để kiểm tra xem một biến không được đặt hoặc được đặt thành chuỗi trống là do một số triển khai của biến [ lệnh (còn được gọi là test) là lỗi. Nếu VAR được đặt thành một cái gì đó như -n, sau đó một số triển khai sẽ làm điều sai khi được [ "${VAR}" = "" ] bởi vì đối số đầu tiên [ được hiểu sai là -n toán tử, không phải chuỗi.


205
2018-04-24 20:39



Thử nghiệm cho một tập hợp biến thành chuỗi rỗng cũng có thể được thực hiện bằng cách sử dụng [ -z "${VAR-set}" ]. - nwellnhof
@nwellnhof: Cảm ơn! Tôi đã cập nhật câu trả lời của mình để sử dụng cú pháp briefer. - Richard Hansen
@ FaheemMitha: Đó không phải lỗi của bạn - câu trả lời của tôi khó đọc. Tôi đã thêm một bảng để hy vọng làm cho câu trả lời rõ ràng hơn. - Richard Hansen
@RichardHansen: Cảm ơn, đó là một bổ sung hữu ích. - Faheem Mitha
Kiểm tra chưa được đặt không đáng tin cậy. Nếu người dùng được gọi set -u hoặc là set -o nounset trong bash, sau đó kiểm tra sẽ chỉ dẫn đến lỗi "bash: VAR: unbound variable". Xem stackoverflow.com/a/13864829 để có một kiểm tra chưa được kiểm tra đáng tin cậy hơn. Tôi đi kiểm tra xem một biến là null hay chưa được đặt là [ -z "${VAR:-}" ]. Kiểm tra của tôi cho dù biến là không trống là [ "${VAR:-}" ]. - Kevin Jin


-z là cách tốt nhất.

Một tùy chọn khác mà tôi đã sử dụng là đặt biến, nhưng nó có thể bị ghi đè bởi một biến khác, ví dụ

export PORT=${MY_PORT:-5432}

Nếu $MY_PORT biến là trống, sau đó PORT được đặt thành 5432, nếu không thì PORT được đặt thành giá trị của MY_PORT. Lưu ý cú pháp bao gồm dấu hai chấm và dấu gạch ngang.


36
2018-06-11 13:19



Vô tình tìm thấy điều này ngày hôm nay, và đó là chính xác những gì tôi muốn. Cảm ơn! Tôi phải chịu đựng set -o nounset trong một số tập lệnh. - opello


Nếu bạn quan tâm đến việc phân biệt các trường hợp thiết lập trống so với trạng thái chưa đặt, hãy xem tùy chọn -u cho bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true

24
2018-05-12 18:21





Một thay thế tôi đã thấy [ -z "$foo" ] là như sau, tuy nhiên tôi không chắc tại sao mọi người sử dụng phương pháp này, bất cứ ai biết?

[ "x${foo}" = "x" ]

Dù sao nếu bạn không cho phép các biến không được đặt (hoặc bằng set -u hoặc là set -o nounset), sau đó bạn sẽ gặp rắc rối với cả hai phương pháp đó. Có một sửa chữa đơn giản cho điều này:

[ -z "${foo:-}" ]

Lưu ý: điều này sẽ để biến của bạn undef.


8
2017-10-20 03:58



Có một nhận xét về giải pháp thay thế cho -z tại pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. Về cơ bản, nó không phải là một thay thế cho -z. Thay vào đó, nó xử lý các trường hợp $foo có thể mở rộng đến cái gì đó bắt đầu bằng một siêu ký tự [ hoặc là test sẽ bị nhầm lẫn bởi. Đặt một không metacharacter tùy ý lúc đầu loại bỏ khả năng đó. - James Sneeringer


Các câu hỏi hỏi làm thế nào để kiểm tra xem một biến là một chuỗi rỗng và câu trả lời tốt nhất đã được đưa ra cho điều đó.
Nhưng tôi đã hạ cánh ở đây sau một thời gian thông qua lập trình bằng php và những gì tôi thực sự tìm kiếm là một kiểm tra như chức năng rỗng trong php làm việc trong một bash shell.
Sau khi đọc các câu trả lời tôi nhận ra tôi đã không suy nghĩ đúng trong bash, nhưng dù sao trong khoảnh khắc đó một chức năng như trống trong php sẽ có được soooo tiện dụng trong mã bash của tôi.
Khi tôi nghĩ điều này có thể xảy ra với người khác, tôi đã quyết định chuyển đổi hàm rỗng của php trong bash

Theo hướng dẫn sử dụng php:
một biến được coi là rỗng nếu nó không tồn tại hoặc nếu giá trị của nó là một trong các biến sau:

  • "" (một chuỗi rỗng)
  • 0 (0 là số nguyên)
  • 0.0 (0 là phao)
  • "0" (0 dưới dạng chuỗi)
  • một mảng trống
  • một biến được khai báo, nhưng không có giá trị

Dĩ nhiên vô giá trị và sai trường hợp không thể được chuyển đổi trong bash, do đó, chúng được bỏ qua.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Ví dụ về cách sử dụng:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Bản giới thiệu:
đoạn mã sau:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

kết quả đầu ra:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

Có nói rằng trong một logic bash các kiểm tra về số không trong chức năng này có thể gây ra vấn đề phụ imho, bất cứ ai sử dụng chức năng này nên đánh giá rủi ro này và có thể quyết định cắt những kiểm tra ra chỉ để lại đầu tiên.


6
2017-08-31 20:11



Bên trong hàm empty - tại sao bạn lại viết [[ $( echo "1" ) ]] ; return thay vì đơn giản return 1 ? - Dor


toàn bộ if-then và -z là không cần thiết.

["$ foo"] && echo "foo không trống"
["$ foo"] || echo "foo thực sự trống rỗng"

5
2018-01-26 14:02



Điều đó sẽ thất bại nếu foo chỉ chứa không gian - Brian
Cũng sẽ thất bại trong một số vỏ nếu foo bắt đầu bằng dấu gạch ngang vì nó được hiểu là một tùy chọn. Ví dụ. trên solaris ksh, zsh và bash không sao cả, sh và / bin / test sẽ thất bại - ktf


Điều này đúng khi đặt $ FOO và trống:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]

4
2018-05-20 20:52