Bagaimana cara menentukan apakah variabel bash kosong?


Jawaban:


1053

Ini akan mengembalikan true jika variabel tidak disetel atau disetel ke string kosong ("").

if [ -z "$VAR" ];

14
Apakah itu termasuk jika variabel IS SET ke nilai ""?
Brent

11
Ya itu ... "-z" menguji string dengan panjang nol.
David Z

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

263
kebalikannya -zadalah-n if [ -n "$VAR" ];
Felipe Alvarez

19
Kutipan ganda memastikan bahwa variabel tidak terpecah. Sederhana $varpada baris perintah akan dibagi dengan spasi putih menjadi daftar parameter, sementara "$var"akan selalu menjadi hanya satu parameter. Mengutip variabel sering kali merupakan praktik yang baik dan menghentikan Anda dari tersandung pada nama file yang mengandung spasi putih (antara lain). Contoh: setelah melakukan a="x --help", coba cat $a- ini akan memberi Anda halaman bantuan cat. Kemudian coba cat "$a"- itu akan (biasanya) mengatakan cat: x --help: No such file or directory. Singkatnya, kutip lebih awal dan sering kutip dan Anda hampir tidak akan pernah menyesalinya.
Score_Under

247

Di Bash, ketika Anda tidak peduli dengan portabilitas ke shell yang tidak mendukungnya, Anda harus selalu menggunakan sintaks braket ganda:

Salah satu dari yang berikut:

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

Di Bash, menggunakan tanda kurung ganda, tanda kutip tidak diperlukan. Anda dapat menyederhanakan tes untuk variabel yang tidak mengandung nilai ke:

if [[ $variable ]]

Sintaks ini kompatibel dengan ksh (setidaknya ksh93, pokoknya). Ini tidak bekerja di POSIX murni atau kulit Bourne yang lebih tua seperti sh atau dash.

Lihat jawaban saya di sini dan BashFAQ / 031 untuk informasi lebih lanjut tentang perbedaan antara tanda kurung ganda dan tunggal.

Anda dapat menguji untuk melihat apakah suatu variabel secara khusus tidak disetel (berbeda dari string kosong):

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

di mana "x" adalah arbitrer.

Jika Anda ingin tahu apakah suatu variabel adalah nol tetapi tidak disetel:

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

1
Itu if [[ $variable ]]bekerja dengan baik untuk saya, dan bahkan tidak membutuhkan set -uyang diminta oleh salah satu solusi yang diusulkan lainnya.
Teemu Leisti

3
Saya pikir ini lebih baik daripada jawaban yang diterima.
qed

2
Mengapa Anda merekomendasikan fitur non-portabel saat melakukannya tidak memberikan manfaat?
Alastair Irvine

19
@AlastairIrvine: Saya menyebutkan portabilitas dalam kalimat pertama dari jawaban saya, judul pertanyaan dan isi berisi kata "Bash" dan pertanyaan tersebut ditandai bash , dan struktur braket ganda memberikan keuntungan yang jelas dalam banyak hal. Dan saya tidak merekomendasikan mencampur gaya braket untuk alasan konsistensi dan perawatan. Jika Anda membutuhkan portabilitas penyebut umum maksimum dan terendah, gunakan shsebagai pengganti Bash. Jika Anda membutuhkan peningkatan kemampuan yang disediakannya, gunakan Bash dan gunakan sepenuhnya.
Dennis Williamson

2
@BrunoBronosky: Saya mengembalikan hasil edit. Tidak ada persyaratan untuk ;pada akhirnya. The thendapat berada di baris berikutnya tanpa titik koma sama sekali.
Dennis Williamson

230

Variabel dalam bash (dan semua shell yang kompatibel dengan POSIX) dapat berupa salah satu dari tiga status:

  • tidak disetel
  • atur ke string kosong
  • setel ke string yang tidak kosong

Sebagian besar waktu Anda hanya perlu tahu apakah suatu variabel diatur ke string yang tidak kosong, tetapi kadang-kadang penting untuk membedakan antara tidak disetel dan ditetapkan ke string kosong.

Berikut ini adalah contoh bagaimana Anda dapat menguji berbagai kemungkinan, dan ia bekerja dalam bash atau shell yang kompatibel dengan POSIX:

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

Ini adalah hal yang sama tetapi dalam bentuk tabel praktis:

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

The ${VAR+foo}membangun memperluas ke string kosong jika VARtidak disetel atau foojika VARdiatur untuk apa pun (termasuk string kosong).

The ${VAR-foo}membangun memperluas untuk nilai VARjika diatur (termasuk set ke string kosong) dan foojika diset. Ini berguna untuk menyediakan default yang dapat ditimpa pengguna (misalnya, ${COLOR-red}mengatakan untuk menggunakan redkecuali variabel COLORtelah disetel ke sesuatu).

Alasan mengapa [ x"${VAR}" = x ]sering direkomendasikan untuk menguji apakah suatu variabel tidak disetel atau disetel ke string kosong adalah karena beberapa implementasi dari [perintah (juga dikenal sebagai test) buggy. Jika VARdiatur ke sesuatu seperti -n, maka beberapa implementasi akan melakukan hal yang salah ketika diberikan [ "${VAR}" = "" ]karena argumen pertama ke [salah ditafsirkan sebagai -noperator, bukan string.


3
Pengujian untuk set variabel ke string kosong juga dapat dilakukan dengan menggunakan [ -z "${VAR-set}" ].
nwellnhof

@nwellnhof: Terima kasih! Saya memperbarui jawaban saya untuk menggunakan sintaks yang lebih singkat.
Richard Hansen

Apa perbedaan antara konstruk pertama dan terakhir? Keduanya berhubungan dengan "VAR tidak disetel atau disetel ke string yang tidak kosong".
Faheem Mitha

1
@FaheemMitha: Itu bukan salahmu - jawabanku sulit dibaca. Saya menambahkan tabel agar mudah-mudahan membuat jawaban lebih jelas.
Richard Hansen

2
Pemeriksaan yang tidak disetel tidak dapat diandalkan. Jika pengguna memanggil set -uatau set -o nounsetdalam bash, maka pengujian hanya akan menghasilkan kesalahan "bash: VAR: unbound variable". Lihat stackoverflow.com/a/13864829 untuk pemeriksaan unset yang lebih andal. Pergi ke saya untuk memeriksa apakah suatu variabel adalah nol atau tidak disetel [ -z "${VAR:-}" ]. Cek saya apakah suatu variabel tidak kosong adalah [ "${VAR:-}" ].
Kevin Jin

38

-z adalah cara terbaik.

Opsi lain yang saya gunakan adalah untuk menetapkan variabel, tetapi dapat ditimpa oleh variabel lain misalnya

export PORT=${MY_PORT:-5432}

Jika $MY_PORTvariabel kosong, maka PORTakan ditetapkan ke 5432, jika PORT diatur ke nilai MY_PORT. Perhatikan sintaksinya termasuk titik dua dan tanda hubung.


Tanpa sengaja menemukan ini hari ini, dan itulah tepatnya yang saya inginkan. Terima kasih! Saya harus mentolerir set -o nounsetdalam beberapa skrip.
opello

24

Jika Anda tertarik membedakan kasus status set-kosong versus tidak disetel, lihat opsi -u untuk 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

Alternatif yang saya [ -z "$foo" ]perhatikan adalah sebagai berikut, namun saya tidak yakin mengapa orang menggunakan metode ini, ada yang tahu?

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

Bagaimanapun juga jika Anda melarang variabel yang tidak disetel (baik oleh set -uatau set -o nounset), maka Anda akan mengalami masalah dengan kedua metode tersebut. Ada perbaikan sederhana untuk ini:

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

Catatan: ini akan membuat variabel Anda undef.


3
Ada komentar tentang alternatif -zdi pubs.opengroup.org/onlinepubs/009695399/utilities/test.html . Pada dasarnya, ini tidak dimaksudkan sebagai alternatif -z. Sebaliknya, ia menangani kasus-kasus di mana $foodapat berkembang menjadi sesuatu yang dimulai dengan metacharacter yang [atau testakan membingungkan. Menempatkan non-metacharacter sewenang-wenang di awal menghilangkan kemungkinan itu.
James Sneeringer

6

The Pertanyaan meminta bagaimana untuk memeriksa apakah suatu variabel string kosong dan jawaban terbaik sudah diberikan untuk itu.
Tapi saya mendarat di sini setelah beberapa waktu berlalu pemrograman dalam php dan apa yang sebenarnya saya cari adalah cek seperti fungsi kosong di php bekerja di bash shell.
Setelah membaca jawaban saya menyadari saya tidak berpikir dengan benar di bash, tapi bagaimanapun pada saat itu fungsi seperti kosong di php akan sangat berguna dalam kode bash saya.
Karena saya pikir ini bisa terjadi pada orang lain, saya memutuskan untuk mengubah fungsi kosong php di bash

Menurut manual php :
variabel dianggap kosong jika tidak ada atau nilainya salah satu dari yang berikut:

  • "" (string kosong)
  • 0 (0 sebagai bilangan bulat)
  • 0,0 (0 sebagai pelampung)
  • "0" (0 sebagai string)
  • sebuah array kosong
  • variabel dideklarasikan, tetapi tanpa nilai

Tentu saja kasus null dan false tidak dapat dikonversi dalam bash, sehingga dihilangkan.

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 "" ) ]]
}



Contoh penggunaan:

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



Demo:
cuplikan berikut:

#!/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

output:

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

Setelah mengatakan bahwa dalam logika bash, cek pada nol pada fungsi ini dapat menyebabkan masalah samping, siapa pun yang menggunakan fungsi ini harus mengevaluasi risiko ini dan mungkin memutuskan untuk memotong cek tersebut sehingga hanya menyisakan yang pertama.


Di dalam fungsi empty- mengapa Anda menulis [[ $( echo "1" ) ]] ; returnbukan hanya return 1?
Dor

5

seluruh if-then dan -z tidak perlu.

["$ foo"] && echo "foo tidak kosong"
["$ foo"] || gema "foo memang kosong"

3
Itu akan gagal jika foo hanya berisi spasi
Brian

2
Juga akan gagal di beberapa shell jika foo dimulai dengan tanda hubung karena ditafsirkan sebagai opsi. Misalnya pada solaris ksh , zsh dan bash tidak ada masalah, sh dan / bin / test akan gagal
ktf

4

Ini benar ketika $ FOO disetel dan kosongkan:

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

4

Secara pribadi lebih suka cara yang lebih jelas untuk memeriksa:

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

1
Beberapa shell tidak menerima tanda sama dengan dobel.
Dennis Williamson

1
Pertanyaannya adalah tentang bash. Saya menggunakan bash. Bekerja dengan baik untuk saya. Apa yang sebenarnya Anda bicarakan?
Fedir RYKHTIK

2
Jika Anda menggunakan Bash, Anda harus menggunakan tanda kurung ganda. Komentar saya sebelumnya adalah pernyataan fakta sederhana bagi mereka yang mungkin membaca jawaban Anda dan menggunakan shell yang berbeda.
Dennis Williamson

kurung kotak tunggal ok dalam hal ini, silakan lihat serverfault.com/questions/52034/...
Luca Borrione

4

ekstensi oneliner dari solusi duffbeer703 :

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

4

5 sen saya: ada juga sintaks yang lebih pendek daripada if ..., yang ini:

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

Baris ini akan menetapkan VALUE jika argumen telah disediakan dan akan mencetak pesan kesalahan yang diawali dengan nomor baris skrip jika terjadi kesalahan (dan akan menghentikan eksekusi skrip).

Contoh lain dapat ditemukan dalam panduan abs (cari «Contoh 10-7»).


0

Bukan jawaban yang pasti, tetapi mengalami trik ini. Jika string yang Anda cari berasal dari "sebuah perintah" maka Anda sebenarnya dapat menyimpan perintah itu dalam env. variabel dan kemudian jalankan setiap kali untuk pernyataan if, maka tidak diperlukan tanda kurung!

Misalnya perintah ini, yang menentukan apakah Anda menggunakan debian:

grep debian /proc/version

contoh lengkap:

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

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

Jadi ini seperti cara tidak langsung (jalankan ulang setiap kali) untuk memeriksa string kosong (kebetulan memeriksa respons kesalahan dari perintah, tetapi juga mengembalikan string kosong).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.