it-swarm-vi.tech

Làm thế nào để xác định nếu một biến bash là trố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 là cách đúng không? (phải có một cái gì đó đơn giản hơn)

784
Brent

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

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, 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 mà không chứa giá trị để:

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} ]]
253

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ỳ Shell 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} xây dựng mở rộng thành chuỗi trống nếu VAR không được đặt hoặc thành foo if VAR được đặt thành bất kỳ thứ gì (bao gồm cả chuỗi trống).

Các ${VAR-foo} xây dựng mở rộng thành giá trị của VAR nếu được đặt (bao gồm đặt thành chuỗi trống) và foo nếu không được đặt. Điều này hữu ích để cung cấp các giá trị mặc định có thể vượt quá người dùng (ví dụ: ${COLOR-red} nói sử dụng red trừ 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 không được đặt hoặc được đặt thành chuỗi trống là do 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ì đó như -n, sau đó một số triển khai sẽ làm sai khi đưa ra [ "${VAR}" = "" ] vì đối số đầu tiên với [ bị hiểu nhầm là -n toán tử, không phải là một chuỗi.

239
Richard Hansen

-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_PORT biế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.

38
Rory

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 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
MikeyB

Một thay thế tôi đã thấy [ -z "$foo" ] là những điều sau đây, 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 -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 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.

8
errant.info

Câu hỏi hỏi cách kiểm tra xem một biến có phải là một chuỗi rỗng 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à thứ tôi thực sự đang tìm kiếm là một kiểm tra như hàm rỗng trong php làm việc 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 thì trong thời điểm đó, một hàm như blank 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 as an integer)
  • 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 nullfalse không thể được chuyển đổi trong bash, vì vậy chúng bị 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 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, việc kiểm tra số 0 trong chức năng này có thể gây ra sự cố 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ỏ những kiểm tra đó chỉ để lại kiểm tra đầu tiên.

6
Luca Borrione

5 xu của tôi: cũng có một cú pháp ngắn hơn if ..., cái 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 abs-guide (tìm kiếm "Ví dụ 10-7").

5
gluk47

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
namewithoutwords

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

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

phần mở rộng oneliner của duffbeer7 's giải pháp:

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

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
4
Fedir RYKHTIK

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ờ là 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).

0
rogerdpack