Làm thế nào để xác định nếu một biến bash là trống?


Câu trả lời:


1053

Đ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" ];

14
Điều đó có bao gồm nếu một biến IS SET thành giá trị "" không?
Brent

11
Có, nó thực hiện ... "-z" kiểm tra chuỗi có độ dài bằng không.
David Z

91
if [ ! -z "$VAR" ];
Aaron Copley

263
nghịch đảo của -z-n if [ -n "$VAR" ];
Felipe Alvarez

19
Các dấu ngoặc kép đảm bảo rằng biến không bị phân tách. Một đơn giản $vartrê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 chỉ là một tham số. 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ỏi vấp vào tên tệp chứa khoảng trắng (trong số những thứ khác). Ví dụ: sau khi thực hiện a="x --help", hãy thử cat $a- nó sẽ cung cấp cho bạn trang trợ giúp cat. Sau đó thử cat "$a"- nó sẽ (thường) nói cat: x --help: No such file or directory. Tóm lại, trích dẫn sớm và trích dẫn thường xuyên và bạn sẽ gần như không bao giờ hối tiếc.
Điểm_Under

247

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 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, dấu ngoặc kép không cần thiết. Bạn có thể đơn giản hóa kiểm tra cho một biến chứa giá trị thành:

if [[ $variable ]]

Cú pháp này tương thích với ksh (ít nhất là ksh93, dù sao đi nữa). Nó không hoạt động trong POSIX thuần túy hoặc các vỏ Bourne cũ hơn như sh hoặc dash.

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

Bạn có thể kiểm tra xem một biến có được đặt riêng hay không (như phân biệt 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 là null nhưng không bỏ đặt:

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

1
Điều đó if [[ $variable ]]làm việc tốt với tôi, và thậm chí không cần đến set -umột trong những giải pháp được đề xuất khác.
Teemu Leisti

3
Tôi nghĩ rằng điều này là tốt hơn so với câu trả lời được chấp nhận.
qed

2
Tại sao bạn lại đề xuất một tính năng không di động khi làm như vậy không mang lại lợi ích gì?
Alastair Irvine

19
@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 đề và nội dung câu hỏi có chứa từ "Bash" và câu hỏi được gắn thẻ bash và cấu trúc khung đôi cung cấp các lợi thế rõ ràng theo nhiều cách. Và tôi không khuyên bạn nên trộn các kiểu khung vì lý do thống nhất và duy trì. Nếu bạn cần tính di động của mẫu số chung tối đa, thấp nhất, hãy sử dụng shthay vì Bash. Nếu bạn cần các khả năng gia tăng mà nó cung cấp, hãy sử dụng Bash và sử dụng nó đầy đủ.
Dennis Williamson

2
@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ó thenthể ở dòng tiếp theo mà không có dấu chấm phẩy nào cả.
Dennis Williamson

230

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

  • không đặt
  • đặt thành chuỗi trống
  • đặt thành một chuỗi không trống

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

Sau đây là các 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ỳ trình bao 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ấu ${VAR+foo}trúc mở rộng thành chuỗi trống nếu VARkhông được đặt hoặc thành foonếu VARđược đặt thành bất kỳ thứ gì (bao gồm cả chuỗi trống).

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

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


3
Kiểm tra một biến được đặt thành chuỗi trố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

Sự khác biệt giữa cấu trúc đầu tiên và cuối cùng là gì? Cả hai đều tương ứng với "VAR không được đặt hoặc được đặt thành một chuỗi không trống".
Faheem Mitha

1
@FaheemMitha: Không phải lỗi của bạn - câu trả lời của tôi rất 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

2
Việc kiểm tra unset không đáng tin cậy. Nếu người dùng đã gọi set -uhoặc set -o nounsettrong bash, thì thử nghiệm sẽ chỉ dẫn đến lỗi "bash: VAR: biến không liên kết". Xem stackoverflow.com/a/13864829 để kiểm tra unset đáng tin cậy hơn. Đi để kiểm tra xem một biến là null hay không đặt là [ -z "${VAR:-}" ]. Kiểm tra của tôi cho dù một biến là không trống là [ "${VAR:-}" ].
Kevin Jin

38

-z là một cách tốt nhất

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

export PORT=${MY_PORT:-5432}

Nếu $MY_PORTbiến trống, sau đó PORTđược đặt thành 5432, nếu không 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.


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 nounsettrong một số kịch bản.
opello

24

Nếu bạn quan tâm đến việc phân biệt các trường hợp đặt trạng thái trống so với không đặ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

8

Một thay thế mà 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, có ai biết không?

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

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

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

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


3
Có một nhận xét về giải pháp thay thế -ztại pubs.opengroup.org/onlinepub/009695399/utilities/test.html . Về cơ bản, nó không có nghĩa là một thay thế cho -z. Thay vào đó, nó xử lý các trường hợp $foocó thể mở rộng sang thứ gì đó bắt đầu bằng metacharacter [hoặc testsẽ bị nhầm lẫn. Đặt một vi khuẩn không metacharacter tùy ý ngay từ đầu sẽ loại bỏ khả năng đó.
James Sneeringer

6

Câu hỏi hỏi làm thế nào để kiểm tra xem một biến có phải là một chuỗi rỗng hay khô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à điều tôi thực sự tìm kiếm là một kiểm tra giống như hàm trống trong php hoạt động trong bash shell.
Sau khi đọc các câu trả lời tôi nhận ra rằng tôi đã không suy nghĩ đúng đắn về bash, nhưng dù sao đi nữa, một hàm như trống trong php sẽ rất tiện trong mã bash của tôi.
Vì 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 trống php trong bash

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

  • "" (một chuỗi trống)
  • 0 (0 dưới dạng số nguyên)
  • 0,0 (0 dưới dạng nổi)
  • "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ị

Tất nhiên các trường hợp nullsai không thể được chuyển đổi trong bash, vì vậy 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 trình diễn:
đoạn trích 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

đầ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

Đã nói rằng trong logic bash, các kiểm tra về số 0 trong hàm này có thể gây ra các vấn đề phụ, bất kỳ 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 bỏ các kiểm tra đó chỉ để lại kiểm tra đầu tiên.


Bên trong chức năng empty- tại sao bạn viết [[ $( echo "1" ) ]] ; returnthay vì đơn giản return 1?
Dor

5

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"

3
Điều đó sẽ thất bại nếu foo chỉ chứa khoảng trắng
Brian

2
Cũng sẽ thất bại trong một số shell 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 , zshbash không có vấn đề gì, sh/ bin / test sẽ thất bại
ktf

4

Điều này đúng chính xác khi $ FOO được đặt và trống:

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

4

Cá nhân thích cách rõ ràng hơn để kiểm tra:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi

1
Một số vỏ không chấp nhận dấu bằng kép.
Dennis Williamson

1
Câu hỏi là về bash. Tôi đang sử dụng bash. Hoạt động tốt cho tôi. Chính xác thì bạn đang nói về cái gì?
Fedir RYKHTIK

2
Nếu bạn đang sử dụng Bash, bạn nên sử dụng dấu ngoặc vuông. Nhận xét trước đây của tôi là một tuyên bố thực tế đơn giản cho những người có thể đọc câu trả lời của bạn và đang sử dụng một vỏ khác.
Dennis Williamson

trong trường hợp dấu ngoặc đơn là ok trong trường hợp này, vui lòng xem serverfault.com/questions/52034/
Khăn

4

oneliner mở rộng giải pháp của duffbeer703 :

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter

4

5 xu của tôi: cũng có một cú pháp ngắn hơn, cú pháp if ...này:

VALUE="${1?"Usage: $0 value"}"

Dòng này sẽ đặt GIÁ TRỊ nếu một đối số đã được cung cấp và sẽ in một thông báo lỗi được thêm vào số dòng kịch bản trong trường hợp có lỗi (và sẽ chấm dứt thực thi tập lệnh).

Một ví dụ khác có thể được tìm thấy trong hướng dẫn abs (tìm kiếm «Ví dụ 10-7»).


0

Không phải là một câu trả lời chính xác, nhưng chạy vào thủ thuật này. Nếu chuỗi bạn đang tìm kiếm đến từ "một lệnh" thì bạn thực sự có thể lưu trữ lệnh trong một env. biến và sau đó thực hiện nó mỗi lần cho câu lệnh if, sau đó không yêu cầu dấu ngoặc!

Ví dụ: lệnh này, xác định nếu bạn đang dùng debian:

grep debian /proc/version

ví dụ đầy đủ:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

Vì vậy, đây giống như một cách gián tiếp (chạy lại mỗi lần) để kiểm tra một chuỗi rỗng (tình cờ kiểm tra phản hồi lỗi từ lệnh, nhưng nó cũng xảy ra khi trả về một chuỗi rỗng).

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.