it-swarm-id.com

Bagaimana cara memeriksa apakah suatu variabel diatur dalam Bash?

Bagaimana saya tahu jika suatu variabel diatur dalam Bash?

Misalnya, bagaimana cara saya memeriksa apakah pengguna memberikan parameter pertama ke suatu fungsi?

function a {
    # if $1 is set ?
}
1270
prosseek

(Biasanya) Cara yang benar

if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

di mana ${var+x} adalah ekspansi parameter yang tidak bernilai apa-apa jika var tidak disetel, dan mengganti string x sebaliknya.

Kutipan Digresi

Kutipan dapat dihilangkan (jadi kita bisa mengatakan ${var+x} daripada "${var+x}") karena sintaks & jaminan penggunaan ini hanya akan meluas ke sesuatu yang tidak memerlukan kuotasi (karena ia meluas ke x (yang tidak mengandung jeda Word sehingga tidak memerlukan penawaran) , atau tidak sama sekali (yang menghasilkan [ -z ], yang dengan mudah mengevaluasi ke nilai yang sama (benar) yang [ -z "" ] lakukan dengan baik)).

Namun, sementara kutipan dapat dihilangkan dengan aman, dan itu tidak segera jelas bagi semua (itu bahkan tidak jelas bagi penulis pertama dari penjelasan kutipan ini yang juga merupakan pembuat kode Bash utama), kadang-kadang akan lebih baik untuk menulis solusi dengan tanda kutip sebagai [ -z "${var+x}" ], dengan biaya yang sangat kecil untuk penalti kecepatan O(1). Penulis pertama juga menambahkan ini sebagai komentar di sebelah kode menggunakan solusi ini memberikan URL untuk jawaban ini, yang sekarang juga termasuk penjelasan mengapa kutipan dapat dihilangkan dengan aman.

(Sering) dengan cara yang salah

if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi

Ini sering salah karena tidak membedakan antara variabel yang tidak disetel dan variabel yang disetel ke string kosong. Artinya, jika var='', maka solusi di atas akan menampilkan "var is blank".

Perbedaan antara tidak disetel dan "disetel ke string kosong" sangat penting dalam situasi di mana pengguna harus menentukan ekstensi, atau daftar properti tambahan, dan yang tidak menentukan default untuk nilai yang tidak kosong, sedangkan menentukan string kosong harus buat skrip menggunakan ekstensi kosong atau daftar properti tambahan.

Perbedaannya mungkin tidak penting dalam setiap skenario. Dalam kasus tersebut [ -z "$var" ] akan baik-baik saja.

1915
Lionel

Untuk memeriksa variabel string bukan nol/bukan nol, mis. Jika disetel, gunakan

if [ -n "$1" ]

Ini kebalikan dari -z. Saya menemukan diri saya menggunakan -n lebih dari -z.

Anda akan menggunakannya seperti:

if [ -n "$1" ]; then
  echo "You supplied the first parameter!"
else
  echo "First parameter not supplied."
fi
756
mbrannig

Berikut ini cara menguji apakah suatu parameter adalah tidak disetel , atau kosong ("Null") atau ditetapkan dengan nilai :

+--------------------+----------------------+-----------------+-----------------+
|                    |       parameter      |     parameter   |    parameter    |
|                    |   Set and Not Null   |   Set But Null  |      Unset      |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-Word} | substitute parameter | substitute Word | substitute Word |
| ${parameter-Word}  | substitute parameter | substitute null | substitute Word |
| ${parameter:=Word} | substitute parameter | assign Word     | assign Word     |
| ${parameter=Word}  | substitute parameter | substitute null | assign Word     |
| ${parameter:?word} | substitute parameter | error, exit     | error, exit     |
| ${parameter?word}  | substitute parameter | substitute null | error, exit     |
| ${parameter:+Word} | substitute Word      | substitute null | substitute null |
| ${parameter+Word}  | substitute Word      | substitute Word | substitute null |
+--------------------+----------------------+-----------------+-----------------+

Sumber: POSIX: Ekspansi Parameter :

Dalam semua kasus yang ditunjukkan dengan "pengganti", ekspresi diganti dengan nilai yang ditunjukkan. Dalam semua kasus yang ditunjukkan dengan "menetapkan", parameter diberi nilai itu, yang juga menggantikan ekspresi.

419
Jens

Sementara sebagian besar teknik yang dinyatakan di sini benar, bash 4.2 mendukung tes aktual untuk keberadaan variabel ( man bash ), daripada menguji nilai variabel.

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

Khususnya, pendekatan ini tidak akan menyebabkan kesalahan ketika digunakan untuk memeriksa variabel yang tidak disetel dalam mode set -u/set -o nounset, tidak seperti banyak pendekatan lain, seperti menggunakan [ -z.

188
Russell Harmon

Ada banyak cara untuk melakukan ini dengan yang berikut ini salah satunya:

if [ -z "$1" ]

Ini berhasil jika $ 1 adalah nol atau tidak disetel

173
ennuikiller

Untuk melihat apakah suatu variabel tidak kosong, saya menggunakan

if [[ $var ]]; then ...       # `$var' expands to a nonempty string

Tes sebaliknya jika variabel tidak disetel atau kosong:

if [[ ! $var ]]; then ...     # `$var' expands to the empty string (set or not)

Untuk melihat apakah suatu variabel disetel (kosong atau kosong), saya menggunakan

if [[ ${var+x} ]]; then ...   # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ...     # Parameter 1 exists (empty or nonempty)

Tes sebaliknya jika variabel tidak disetel:

if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ...   # We were called with no arguments
61
phkoester

Saya selalu menemukan tabel POSIX di jawaban lain lambat untuk grok, jadi inilah pendapat saya:

   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |          ""           |       "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |          ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |          ""           |       exit 127        |
 + |  ${VARIABLE+default} | "default"  |       "default"       |          ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |       "default"       |       "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} | "default"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

Perhatikan bahwa setiap grup (dengan dan tanpa tanda titik dua sebelumnya) memiliki case set dan unset yang sama, jadi satu-satunya hal yang berbeda adalah bagaimana kasus kosong ditangani.

Dengan titik dua sebelumnya, blank dan unset sama, jadi saya akan menggunakan yang memungkinkan (mis. Gunakan :=, bukan hanya =, karena case kosong tidak konsisten).

Judul:

  • set berarti VARIABLE tidak kosong (VARIABLE="something")
  • empty berarti VARIABLE kosong/null (VARIABLE="")
  • tidak disetel berarti VARIABLE tidak ada (unset VARIABLE)

Nilai:

  • $VARIABLE berarti hasilnya adalah nilai asli dari variabel.
  • "default" berarti hasilnya adalah string pengganti yang disediakan.
  • "" berarti hasilnya nol (string kosong).
  • exit 127 berarti skrip berhenti dijalankan dengan kode keluar 127.
  • $(VARIABLE="default") berarti hasilnya adalah nilai asli dari variabel dan string pengganti yang diberikan ditugaskan ke variabel untuk digunakan di masa mendatang.
53
deizel

Pada versi modern Bash (4.2 atau lebih baru, saya pikir; saya tidak tahu pasti), saya akan mencoba ini:

if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    echo "Variable is unset"
Elif [ -z "$SOMEVARIABLE" ]
then
    echo "Variable is set to an empty string"
else
    echo "Variable is set to some string"
fi
31
Seamus Connor
if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

Meskipun untuk argumen biasanya yang terbaik untuk menguji $ #, yang merupakan jumlah argumen, menurut pendapat saya.

if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi
19
Paul Creasey

Anda ingin keluar jika tidak disetel

Ini berhasil untuk saya. Saya ingin skrip saya keluar dengan pesan kesalahan jika parameter tidak disetel.

#!/usr/bin/env bash

set -o errexit

# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"

Ini kembali dengan kesalahan saat dijalankan

[email protected]:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument

Periksa saja, tidak ada jalan keluar - Kosong dan Tidak diset adalah INVALID

Coba opsi ini jika Anda hanya ingin memeriksa apakah nilai set = VALID atau tidak disetel/kosong = INVALID.

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Atau, Bahkan tes singkat ;-)

[ "${TSET:-}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"

Periksa saja, tidak ada jalan keluar - Hanya kosong yang INVALID

Dan ini adalah jawaban untuk pertanyaan itu. Gunakan ini jika Anda hanya ingin memeriksa apakah nilai set/kosong = VALID atau tidak diset = INVALID.

CATATAN, "1" dalam "..- 1}" tidak signifikan, bisa berupa apa saja (seperti x)

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Tes singkat

[ "${TSET+1}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"

Saya mendedikasikan jawaban ini untuk @ mklement0 (komentar) yang menantang saya untuk menjawab pertanyaan secara akurat.

Referensi http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

15
Jarrod Chesney

Untuk memeriksa apakah suatu variabel diatur dengan nilai yang tidak kosong, gunakan [ -n "$x" ], seperti yang telah ditunjukkan orang lain.

Sebagian besar waktu, itu adalah ide yang baik untuk memperlakukan variabel yang memiliki nilai kosong dengan cara yang sama dengan variabel yang tidak disetel. Tetapi Anda dapat membedakan keduanya jika Anda perlu: [ -n "${x+set}" ] ("${x+set}" berkembang menjadi set jika x diatur dan ke string kosong jika x tidak disetel).

Untuk memeriksa apakah suatu parameter telah dilewati, uji $#, yang merupakan jumlah parameter yang diteruskan ke fungsi (atau ke skrip, ketika tidak ada dalam suatu fungsi) (lihat jawaban Paul ).

14
Gilles

Baca bagian "Ekspansi Parameter" dari halaman manual bash. Ekspansi parameter tidak memberikan tes umum untuk variabel yang ditetapkan, tetapi ada beberapa hal yang dapat Anda lakukan untuk parameter jika tidak diatur.

Sebagai contoh:

function a {
    first_arg=${1-foo}
    # rest of the function
}

akan menetapkan first_arg sama dengan $1 jika ditugaskan, jika tidak menggunakan nilai "foo". Jika a benar-benar harus mengambil parameter tunggal, dan tidak ada default yang baik, Anda dapat keluar dengan pesan kesalahan ketika tidak ada parameter yang diberikan:

function a {
    : ${1?a must take a single argument}
    # rest of the function
}

(Perhatikan penggunaan : sebagai perintah nol, yang hanya memperluas nilai argumennya. Kami tidak ingin melakukan apa pun dengan $1 dalam contoh ini, cukup keluar jika tidak disetel)

14
chepner

Dalam bash Anda dapat menggunakan -v di dalam [[ ]] bawaan:

#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR
13
AlejandroVD

Bagi mereka yang ingin memeriksa unset atau kosong ketika dalam skrip dengan set -u :

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

Pemeriksaan [ -z "$var" ] reguler akan gagal dengan var; unbound variable jika set -u tetapi [ -z "${var-}" ]expands untuk mengosongkan string jika var tidak diset tanpa gagal.

12
ecerulm

Jawaban di atas tidak berfungsi ketika opsi Bash set -u diaktifkan. Selain itu, mereka tidak dinamis, mis., Bagaimana cara menguji variabel dengan nama "dummy" didefinisikan? Coba ini:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # Tricky.  Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
    # is defined with this construct: [ ! -z "$var" ].  Instead, we must use default value
    # substitution with this construct: [ ! -z "${var:-}" ].  Normally, a default value follows the
    # operator ':-', but here we leave it blank for empty (null) string.  Finally, we need to
    # substitute the text from $1 as 'var'.  This is not allowed directly in Bash with this
    # construct: [ ! -z "${$1:-}" ].  We need to use indirection with eval operator.
    # Example: $1="var"
    # Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
    # Code  execute: [ ! -z ${var:-} ]
    eval "[ ! -z \${$1:-} ]"
    return $?  # Pedantic.
}

Terkait: Dalam Bash, bagaimana cara menguji jika variabel didefinisikan dalam mode "-u"

4
kevinarpe

Anda dapat melakukan:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}
4
codaddict

Menggunakan [[ -z "$var" ]] adalah cara termudah untuk mengetahui apakah suatu variabel disetel atau tidak, tetapi opsi itu -z tidak membedakan antara variabel yang tidak disetel dan variabel yang disetel ke string kosong:

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

Cara terbaik untuk memeriksanya sesuai dengan jenis variabel: variabel env, parameter atau variabel biasa.

Untuk variabel env:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

Untuk parameter (misalnya, untuk memeriksa keberadaan parameter $5):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

Untuk variabel reguler (menggunakan fungsi bantu, lakukan dengan cara yang elegan):

function declare_var {
   declare -p "$1" &> /dev/null
}
declare_var "var_name" && echo "Set" || echo "Unset"

Catatan:

  • $#: memberi Anda jumlah parameter posisi.
  • declare -p: memberi Anda definisi variabel yang dilewatkan sebagai parameter. Jika ada, kembalikan 0, jika tidak, kembalikan 1 dan cetak pesan kesalahan.
  • &> /dev/null: menekan output dari declare -p tanpa mempengaruhi kode pengembaliannya.
4
Peregring-lk

Cara pilihan saya adalah ini:

$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set

Jadi pada dasarnya, jika variabel diatur, itu menjadi "negasi dari hasil false" (apa yang akan menjadi true = "diatur").

Dan, jika tidak disetel, itu akan menjadi "negasi dari hasil true" (karena hasil kosong mengevaluasi ke true) (jadi akan berakhir menjadi false = "TIDAK disetel").

1
Aquarius Power

Dalam sebuah Shell Anda dapat menggunakan operator -z yang Benar jika panjang string adalah nol.

Satu kalimat sederhana untuk menetapkan MY_VAR default jika tidak disetel, jika tidak, Anda dapat menampilkan pesan:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."
1
kenorb

Inilah yang saya gunakan setiap hari:

#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}

Ini berfungsi dengan baik di Linux dan Solaris hingga bash 3.0.

bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1
0
fr00tyl00p

Saya selalu menggunakan ini, berdasarkan fakta bahwa tampaknya mudah dimengerti oleh siapa saja yang melihat kode untuk pertama kalinya:

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

Dan, jika ingin memeriksa apakah tidak kosong;

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi

Itu dia.

0
mijnnaam

Saya menemukan (banyak) kode yang lebih baik untuk melakukan ini jika Anda ingin memeriksa apa pun di [email protected].

 jika [[$ 1 = ""]] 
 maka 
 gema '$ 1 kosong' 
 lain 
 gema '$ 1 terisi' 
 fi 

Kenapa ini semua? Semua yang ada di [email protected] ada di Bash, tetapi secara default kosong, jadi test -z dan test -n tidak bisa membantu Anda.

Pembaruan: Anda juga dapat menghitung jumlah karakter dalam suatu parameter.

 jika [$ {# 1} = 0] 
 maka 
 gema '$ 1 kosong' 
 lain 
 gema '$ 1 terisi' 
 fi 
0
Zlatan
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
0
Graham

Saya suka fungsi bantu untuk menyembunyikan detail kasar bash. Dalam hal ini, melakukannya menambah lebih banyak kekasaran (tersembunyi):

# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

Karena saya pertama kali memiliki bug dalam implementasi ini (terinspirasi oleh jawaban Jens dan Lionel), saya datang dengan solusi yang berbeda:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

Saya merasa lebih lurus ke depan, lebih malu dan lebih mudah dipahami/diingat. Uji kasus menunjukkan itu setara:

function main()
{
  declare -i xyz
  local foo
  local bar=
  local baz=''

  IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"
  IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"
  IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"
  IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"

  IsDeclared xyz; echo "IsDeclared xyz: $?"
  IsDeclared foo; echo "IsDeclared foo: $?"
  IsDeclared bar; echo "IsDeclared bar: $?"
  IsDeclared baz; echo "IsDeclared baz: $?"
}

main

Kasing uji juga menunjukkan bahwa local var tidakTIDAKmenyatakan var (kecuali diikuti oleh '='). Untuk beberapa waktu saya pikir saya mendeklarasikan variabel dengan cara ini, hanya untuk menemukan sekarang bahwa saya hanya menyatakan niat saya ... Ini adalah no-op, saya kira.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
Bilah IsDeclared: 0
IsDeclared baz: 0

BONUS: usecase

Saya sebagian besar menggunakan tes ini untuk memberikan (dan mengembalikan) parameter ke fungsi dengan cara agak "elegan" dan aman (hampir menyerupai antarmuka ...):

#auxiliary functions
function die()
{
  echo "Error: $1"; exit 1
}

function assertVariableDeclared()
{
  IsDeclared "$1" || die "variable not declared: $1"
}

function expectVariables()
{
  while (( $# > 0 )); do
    assertVariableDeclared $1; shift
  done
}

# actual example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

Jika dipanggil dengan semua, variabel harus dideklarasikan:

Halo Dunia!

lain:

Kesalahan: variabel tidak dideklarasikan: outputStr

0
Daniel S
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi

if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi
0
solidsnack
[[ $foo ]]

Atau

(( ${#foo} ))

Atau

let ${#foo}

Atau

declare -p foo
0
Steven Penny