if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens
210
Catatan untuk para pencari solusi: Ada banyak jawaban berperingkat tinggi untuk pertanyaan ini yang menjawab pertanyaan "variabel tidak kosong". Solusi koreksi lebih banyak ("adalah set variabel") disebutkan dalam jawaban oleh Jens dan Lionel di bawah ini.
Nathan Kidd
8
Russell Harmon dan Seamus juga benar dengan -vpengujian mereka , meskipun ini tampaknya hanya tersedia pada versi baru bashdan tidak portabel di seluruh cangkang.
Graeme
5
Seperti yang ditunjukkan oleh @NathanKidd, solusi yang benar diberikan oleh Lionel dan Jens. prosseek, Anda harus mengalihkan jawaban yang Anda terima ke salah satunya.
Garrett
3
... atau jawaban yang salah dapat di-downvotasikan oleh yang lebih cerdas di antara kita, karena @prosseek tidak mengatasi masalah tersebut.
dan3
Jawaban:
2305
(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 mengevaluasi apa-apa jika vartidak disetel, dan mengganti string xsebaliknya.
Kutipan Digresi
Kutipan dapat dihilangkan (jadi kita dapat mengatakan ${var+x}alih-alih "${var+x}") karena sintaks & penggunaan ini menjamin ini hanya akan meluas ke sesuatu yang tidak memerlukan penawaran (karena diperluas ke x(yang tidak mengandung kata istirahat sehingga tidak perlu mengutip), atau untuk tidak ada (yang menghasilkan [ -z ], yang dengan mudah mengevaluasi nilai yang sama (benar) yang [ -z "" ]berlaku juga)).
Namun, sementara kutipan dapat dihilangkan dengan aman, dan itu tidak segera jelas bagi semua (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 kutipan sebagai [ -z "${var+x}" ], dengan biaya yang sangat kecil dari 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 mencakup 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-kasus itu [ -z "$var" ]akan baik-baik saja.
@ Garrett, hasil edit Anda membuat jawaban ini salah, ${var+x}adalah pengganti yang tepat untuk digunakan. Menggunakan [ -z ${var:+x} ]tidak menghasilkan hasil yang berbeda dari [ -z "$var" ].
Graeme
11
Ini tidak berhasil. Saya mendapatkan "tidak disetel" terlepas dari apakah var diatur ke nilai atau tidak (dibersihkan dengan "unset var", "echo $ var" tidak menghasilkan keluaran).
Brent212
10
Untuk sintaks solusi $ {parameter + word}, bagian manual resmi adalah gnu.org/software/bash/manual/… ; Namun, bug dalam hal itu, itu tidak terlalu jelas menyebutkan sintaks ini tetapi mengatakan hanya mengutip (Menghilangkan titik dua [":"] menghasilkan tes hanya untuk parameter yang tidak disetel .. $ {parameter: + word} [berarti] Jika parameter nol atau tidak disetel, tidak ada yang diganti, jika tidak, ekspansi kata akan diganti.); ref pubs.opengroup.org/onlinepubs/9699919799/utilities/… yang dikutip (memiliki banyak pengetahuan) memiliki dokumen yang lebih jelas di sini.
Destiny Architect
7
Sepertinya tanda kutip diperlukan ketika Anda menggunakan banyak ekspresi, mis. [ -z "" -a -z ${var+x} ]Mendapat bash: [: argument expectedbash 4.3-ubuntu (tetapi tidak misalnya zsh). Saya benar-benar tidak suka jawabannya menggunakan sintaks yang kebetulan berfungsi dalam beberapa kasus.
FauxFaux
41
Menggunakan simple [ -z $var ]tidak lebih "salah" dari menghilangkan tanda kutip. Either way, Anda membuat asumsi tentang input Anda. Jika Anda baik-baik saja memperlakukan string kosong sebagai tidak disetel, [ -z $var ]itu saja yang Anda butuhkan.
nshew
910
Untuk memeriksa variabel string bukan-nol / bukan-nol, yaitu jika disetel, gunakan
if[-n "$1"]
Ini kebalikan dari -z. Saya menemukan diri saya menggunakan -nlebih dari -z.
Anda akan menggunakannya seperti:
if[-n "$1"];then
echo "You supplied the first parameter!"else
echo "First parameter not supplied."fi
Saya biasanya lebih suka [[ ]]lebih [ ], karena [[ ]]lebih kuat dan menyebabkan masalah kurang dalam situasi tertentu (lihat pertanyaan ini untuk penjelasan tentang perbedaan antara keduanya). Pertanyaannya secara khusus meminta solusi bash dan tidak menyebutkan persyaratan portabilitas.
Aliran
18
Pertanyaannya adalah bagaimana seseorang dapat melihat apakah suatu variabel diatur . Maka Anda tidak dapat mengasumsikan bahwa variabel yang ditetapkan.
HelloGoodbye
7
Saya setuju, []berfungsi lebih baik terutama untuk skrip shell (non-bash).
Hengjie
73
Gagal aktif set -u.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
63
Perhatikan bahwa -nini adalah tes default, jadi lebih sederhana [ "$1" ]atau [[ $1 ]]berfungsi juga. Perhatikan juga bahwa dengan [[ ]]mengutip tidak perlu .
tgl
478
Berikut cara menguji apakah parameter tidak disetel , atau kosong ("Null") atau disetel dengan nilai :
+--------------------+----------------------+-----------------+-----------------+|Expression| parameter | parameter | parameter ||in script:|Set and NotNull|SetButNull|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 |+--------------------+----------------------+-----------------+-----------------+
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.
Untuk menunjukkan ini dalam tindakan:
+--------------------+----------------------+-----------------+-----------------+|Expression| FOO="world"| FOO=""| unset FOO ||in script:|(Set and NotNull)|(SetButNull)|(Unset)|+--------------------+----------------------+-----------------+-----------------+| ${FOO:-hello}| world | hello | hello || ${FOO-hello}| world |""| hello || ${FOO:=hello}| world | FOO=hello | FOO=hello || ${FOO=hello}| world |""| FOO=hello || ${FOO:?hello}| world | error, exit | error, exit || ${FOO?hello}| world |""| error, exit || ${FOO:+hello}| hello |""|""|| ${FOO+hello}| hello | hello |""|+--------------------+----------------------+-----------------+-----------------+
@ HaloGoodbye Ya itu berhasil: set foo; echo ${1:-set but null or unset}echo "foo"; set --; echo ${1:-set but null or unset}gema ditetapkan tetapi nol ...
Jens
4
@ HaloGoodbye Parameter posisi dapat diatur dengan, eh, set:-)
Jens
95
Jawaban ini sangat membingungkan. Adakah contoh praktis tentang cara menggunakan tabel ini?
Ben Davis
12
@BenDavis Detailnya dijelaskan dalam tautan ke standar POSIX, yang merujuk pada bab dari tabel mana. Satu konstruk yang saya gunakan di hampir semua skrip yang saya tulis adalah : ${FOOBAR:=/etc/foobar.conf}untuk menetapkan nilai default untuk variabel jika tidak disetel atau null.
Jens
1
parameteradalah nama variabel apa saja. wordadalah beberapa string untuk menggantikan tergantung pada sintaksis dalam tabel yang Anda gunakan, dan apakah variabel $parameterdiatur, ditetapkan tetapi null, atau tidak disetel. Bukan untuk membuat hal-hal lebih rumit, tetapi wordjuga bisa memasukkan variabel! Ini bisa sangat berguna untuk melewatkan argumen opsional yang dipisahkan oleh karakter. Misalnya: ${parameter:+,${parameter}}menampilkan koma yang dipisahkan ,$parameterjika diset tetapi tidak nol. Dalam hal ini, wordadalah,${parameter}
TrinitronX
260
Sementara sebagian besar teknik yang dinyatakan di sini adalah benar, bash 4.2 mendukung tes aktual untuk kehadiran variabel ( man bash ), daripada menguji nilai variabel.
Khususnya, pendekatan ini tidak akan menyebabkan kesalahan ketika digunakan untuk memeriksa variabel set -u/ set -o nounsetmode yang tidak disetel , tidak seperti banyak pendekatan lain, seperti menggunakan [ -z.
Dalam bash 4.1.2, terlepas dari apakah variabel diatur, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected-bash: syntax error near 'aaa'
Dan
32
Argumen '-v' pada builtin 'test' ditambahkan di bash 4.2.
Ti Strga
19
argumen -v ditambahkan sebagai pelengkap opsi -u shell (nounset). Dengan 'nounset' dihidupkan (set -u), shell akan mengembalikan kesalahan dan berakhir, jika tidak interaktif. $ # bagus untuk memeriksa parameter posisi. Namun, variabel bernama memerlukan beberapa cara lain, selain clobbering, untuk mengidentifikasi mereka sebagai tidak disetel. Sangat disayangkan bahwa fitur ini datang sangat terlambat karena banyak yang terikat dengan versi yang lebih awal, dalam hal ini mereka tidak dapat menggunakannya. Satu-satunya pilihan lain adalah dengan menggunakan trik atau 'peretasan' untuk menyiasatinya seperti yang ditunjukkan di atas tetapi itu paling tidak elegan.
osirisgothra
2
Catatan ini tidak berfungsi untuk variabel yang dideklarasikan tetapi tidak disetel. misalnyadeclare -a foo
miken32
17
Inilah sebabnya saya terus membaca setelah jawaban yang diterima / terpilih tertinggi.
Joe
176
Ada banyak cara untuk melakukan ini dengan yang berikut ini salah satunya:
if[-z "$1"]
Ini berhasil jika $ 1 adalah nol atau tidak disetel
Ada perbedaan antara parameter yang tidak disetel dan parameter dengan nilai nol.
chepner
21
Saya hanya ingin menjadi bertele-tele dan menunjukkan ini adalah jawaban yang berlawanan dengan apa yang diajukan pertanyaan. Pertanyaan bertanya apakah variabel diatur, bukan jika variabel tidak diatur.
Philluminati
47
[[ ]]hanyalah perangkap portabilitas. if [ -n "$1" ]harus digunakan di sini.
Jens
73
Jawaban ini salah. Pertanyaannya menanyakan cara untuk mengetahui apakah suatu variabel disetel, bukan apakah itu disetel ke nilai yang tidak kosong. Diberikan foo="", $foomemiliki nilai, tetapi -zhanya akan melaporkan bahwa itu kosong. Dan -z $fooakan meledak jika sudah set -o nounset.
Keith Thompson
4
Itu tergantung pada definisi "variabel diatur". Jika Anda ingin memeriksa apakah variabel diatur ke string bukan nol , maka jawaban mbranning sudah benar. Tetapi jika Anda ingin memeriksa apakah variabel dideklarasikan tetapi tidak diinisialisasi (yaitu foo=), maka jawaban Russel benar.
Aliran
77
Saya selalu menemukan tabel POSIX di jawaban lain lambat untuk grok, jadi inilah pendapat saya:
Perhatikan bahwa setiap kelompok (dengan dan tanpa usus besar sebelumnya) memiliki set dan kasus yang tidak disetel yang sama , jadi satu-satunya hal yang berbeda adalah bagaimana kasus-kasus kosong ditangani.
Dengan usus besar sebelumnya, case kosong dan unset identik, jadi saya akan menggunakan yang mungkin (yaitu penggunaan :=, bukan hanya =, karena case kosong tidak konsisten).
Judul:
set berarti VARIABLEnon-kosong ( VARIABLE="something")
kosong berarti VARIABLEkosong / nol ( VARIABLE="")
tidak disetel berarti VARIABLEtidak 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 depan.
Anda memperbaiki hanya kesalahan pengodean aktual (contoh tipuan yang tidak diinginkan ketika bekerja dengan variabel). Saya membuat edit untuk memperbaiki beberapa kasus lagi di mana dolar membuat perbedaan dalam menafsirkan deskripsi. BTW, semua variabel shell (dengan pengecualian array) adalah variabel string; mungkin saja mengandung string yang dapat diartikan sebagai angka. Berbicara tentang string hanya mengaburkan pesan. Kutipan tidak ada hubungannya dengan string, mereka hanya sebuah alternatif untuk melarikan diri. VARIABLE=""dapat ditulis sebagai VARIABLE=. Namun, yang pertama lebih mudah dibaca.
Palec
Terima kasih untuk tabelnya, ini sangat berguna, namun saya mencoba membuat skrip keluar jika tidak disetel atau kosong. Tetapi kode keluar yang saya dapatkan adalah 1 bukan 127.
Astronaut
64
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 allif[[! ${1+x}]];then...# We were called with no arguments
Saya juga telah menggunakan ini untuk sementara waktu; hanya dalam cara yang dikurangi:[ $isMac ] && param="--enable-shared"
@ Bhaskar Saya pikir itu karena jawaban ini sudah memberikan jawaban yang pada dasarnya sama (gunakan ${variable+x}untuk mengatur xiff $variable) hampir setengah tahun sebelumnya. Juga memiliki lebih banyak detail menjelaskan mengapa itu benar.
Mark Haferkamp
tetapi ${variable+x}kurang dapat dibaca (& jelas)
knocte
35
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 $ sigilthen
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
Perhatikan juga yang [ -v "$VARNAME" ]tidak salah, tetapi cukup lakukan tes yang berbeda. Misalkan VARNAME=foo; kemudian memeriksa apakah ada variabel bernama fooyang disetel.
chepner
5
Catatan untuk mereka yang menginginkan portabilitas, -vtidak sesuai dengan POSIX
kzh
Jika salah satu mendapat [: -v: unexpected operator, kita harus memastikan untuk menggunakan bashbukan sh.
koppor
25
if["$1"!=""];then
echo \$1 is setelse
echo \$1 is not setfi
Meskipun untuk argumen biasanya yang terbaik untuk menguji $ #, yang merupakan jumlah argumen, menurut pendapat saya.
if[ $# -gt 0 ]; then
echo \$1 is setelse
echo \$1 is not setfi
Tes pertama mundur; Saya pikir Anda ingin [ "$1" != "" ](atau [ -n "$1" ]) ...
Gordon Davisson
10
Ini akan gagal jika $1diatur ke string kosong.
HelloGoodbye,
2
Bagian kedua dari jawaban (menghitung parameter) adalah solusi yang berguna untuk bagian pertama dari jawaban yang tidak berfungsi saat $1diatur ke string kosong.
Mark Berry
Ini akan gagal jika set -o nounsetaktif.
Flimm
21
Catatan
Saya memberikan jawaban yang sangat terfokus pada Bash karena bashtag tersebut.
Jawaban singkat
Selama Anda hanya berurusan dengan variabel bernama di Bash, fungsi ini harus selalu memberi tahu Anda jika variabel telah ditetapkan, bahkan jika itu adalah array kosong.
variable-is-set(){
declare -p "$1"&>/dev/null
}
Kenapa ini bekerja?
Dalam Bash (setidaknya sejauh 3.0), jika varmerupakan variabel yang dideklarasikan / ditetapkan, maka declare -p varoutput sebuah declareperintah yang akan mengatur variabel varuntuk apa pun jenis dan nilainya saat ini, dan mengembalikan kode status 0(sukses). Jika vartidak dideklarasikan, kemudian declare -p varmenampilkan pesan kesalahan ke stderrdan mengembalikan kode status 1. Menggunakan &>/dev/null, mengalihkan baik reguler stdoutdan stderroutput ke /dev/null, tidak pernah terlihat, dan tanpa mengubah kode status. Dengan demikian fungsi hanya mengembalikan kode status.
Mengapa metode lain (kadang-kadang) gagal di Bash
[ -n "$var" ]: Ini hanya memeriksa jika ${var[0]}tidak kosong. (Dalam Bash, $varsama dengan ${var[0]}.)
[ -n "${var+x}" ]: Ini hanya memeriksa jika ${var[0]}diatur.
[ "${#var[@]}" != 0 ]: Ini hanya memeriksa jika setidaknya satu indeks $vardiatur.
Ketika metode ini gagal di Bash
Ini hanya bekerja untuk variabel bernama (termasuk $_), tidak variabel khusus tertentu ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ..., dan setiap saya mungkin sudah lupa). Karena tidak satupun dari ini adalah array, gaya POSIX [ -n "${var+x}" ]berfungsi untuk semua variabel khusus ini. Tetapi berhati-hatilah untuk membungkusnya dalam suatu fungsi karena banyak variabel khusus mengubah nilai / keberadaan ketika fungsi dipanggil.
Catatan kompatibilitas shell
Jika naskah Anda memiliki array dan Anda mencoba untuk membuatnya kompatibel dengan banyak kerang mungkin, maka pertimbangkan untuk menggunakan typeset -pbukan declare -p. Saya pernah membaca bahwa ksh hanya mendukung yang pertama, tetapi belum dapat menguji ini. Saya tahu bahwa Bash 3.0+ dan Zsh 5.5.1 masing-masing mendukung keduanya , typeset -pdan declare -phanya berbeda satu yang merupakan alternatif untuk yang lain. Tapi saya belum menguji perbedaan di luar dua kata kunci tersebut, dan saya belum menguji shell lain.
Jika Anda membutuhkan skrip agar POSIX sh kompatibel, maka Anda tidak dapat menggunakan array. Tanpa array, [ -n "{$var+x}" ]berfungsi.
Kode perbandingan untuk berbagai metode di Bash
Fungsi ini menghapus variabel var, evalsebagai kode yang diteruskan, menjalankan tes untuk menentukan apakah vardiatur oleh evalkode d, dan akhirnya menunjukkan kode status yang dihasilkan untuk pengujian yang berbeda.
Saya melewatkan test -v var,, [ -v var ]dan [[ -v var ]]karena mereka menghasilkan hasil yang identik dengan standar POSIX [ -n "${var+x}" ], sementara membutuhkan Bash 4.2+. Saya juga melewatkan typeset -pkarena sama seperti declare -pdi shell saya sudah diuji (Bash 3.0 hingga 5.0, dan Zsh 5.5.1).
is-var-set-after(){# Set var by passed expression.
unset var
eval"$1"# Run the tests, in increasing order of accuracy.[-n "$var"]# (index 0 of) var is nonempty
nonempty=$?[-n "${var+x}"]# (index 0 of) var is set, maybe empty
plus=$?["${#var[@]}"!=0]# var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?# Show test results.
printf '%30s: %2s %2s %2s %2s\n'"$1" $nonempty $plus $count $declared
}
Kode uji kasus
Perhatikan bahwa hasil tes mungkin tidak terduga karena Bash memperlakukan indeks array non-numerik sebagai "0" jika variabel belum dinyatakan sebagai array asosiatif. Juga, array asosiatif hanya berlaku di Bash 4.0+.
# Header.
printf '%30s: %2s %2s %2s %2s\n'"test"'-n''+x''#@''-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.
is-var-set-after "var=foo"# 0 0 0 0
is-var-set-after "var=(foo)"# 0 0 0 0
is-var-set-after "var=([0]=foo)"# 0 0 0 0
is-var-set-after "var=([x]=foo)"# 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)"# 0 0 0 0# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"# 1 0 0 0
is-var-set-after "var=([0]='')"# 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"# 1 1 0 0
is-var-set-after "var=([1]=foo)"# 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)"# 1 1 0 0# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"# 1 1 1 0
is-var-set-after "declare -a var"# 1 1 1 0
is-var-set-after "declare -A var"# 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"# 1 1 1 1
Uji keluaran
Tes mnemonik dalam berkorespondensi baris header untuk [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], dan declare -p varmasing-masing.
declare -p var &>/dev/null apakah (100%?) dapat diandalkan untuk menguji variabel bernama di Bash sejak setidaknya 3,0.
[ -n "${var+x}" ] dapat diandalkan dalam situasi yang sesuai dengan POSIX, tetapi tidak dapat menangani array.
Tes lain ada untuk memeriksa apakah suatu variabel adalah kosong, dan untuk memeriksa variabel yang dideklarasikan dalam shell lain. Tetapi tes ini tidak cocok untuk skrip Bash atau POSIX.
Dari jawaban yang saya coba, yang ini ( declare -p var &>/dev/null) adalah SATU-SATUNYA yang berfungsi. TERIMA KASIH!
user1387866
2
@ mark-haferkamp Saya mencoba mengedit jawaban Anda untuk menambahkan kritis sebelumnya "/" ke kode fungsi Anda sehingga terbaca ... &> /dev/nulltetapi SO tidak akan membiarkan saya mengedit satu karakter 🙄 (harus> 6 karakter - bahkan mencoba menambah spasi putih tetapi tidak berhasil). Juga, mungkin ada baiknya mengubah fungsi untuk beralih ke $1variabel bernama sampel (misalnya OUTPUT_DIR) karena seperti yang Anda tunjukkan, variabel khusus seperti $1tidak berfungsi di sini. Bagaimanapun, ini adalah pengeditan yang kritis jika tidak, kode tersebut mencari untuk membuat file yang disebut nulldalam direktori relatif bernama dev. BTW - jawaban yang bagus!
joehanna
Juga, menggunakan nama variabel tanpa awalan $ juga berfungsi: declare -p PATH &> /dev/nullmengembalikan 0 di mana sebagai declare -p ASDFASDGFASKDF &> /dev/nullpengembalian 1. (pada bash 5.0.11 (1) -release)
joehanna
1
Kerja bagus! 1 kata hati-hati: declare varmenyatakan var variabel tetapi tidak mengaturnya dalam hal set -o nounset: Uji dengandeclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche
@joehanna Terima kasih telah menangkap yang hilang /! Saya memperbaikinya, tapi saya pikir logikanya cukup membingungkan untuk menjamin suatu fungsi, terutama mengingat komentar @ xebeche. @ xebeche Itu tidak nyaman untuk jawaban saya.… Sepertinya saya harus mencoba sesuatu seperti declare -p "$1" | grep =atau test -v "$1".
Mark Haferkamp
19
Bagi mereka yang ingin memeriksa tidak disetel atau kosong ketika dalam skrip dengan set -u:
if[-z "${var-}"];then
echo "Must provide var environment variable. Exiting...."
exit 1fi
Pemeriksaan reguler [ -z "$var" ]akan gagal var; unbound variablejika set -utetapi [ -z "${var-}" ]berkembang menjadi string kosong jika vartidak disetel tanpa gagal.
Anda kehilangan titik dua. Seharusnya ${var:-}tidak ${var-}. Tapi di Bash, saya bisa memastikan itu berfungsi bahkan tanpa tanda titik dua.
Palec
3
${var:-}dan ${var-}berarti hal yang berbeda. ${var:-}akan diperluas ke string kosong jika vartidak disetel atau null dan ${var-}akan diperluas ke string kosong hanya jika tidak disetel.
RubenLaguna
Baru belajar sesuatu yang baru, terima kasih! Menghilangkan titik dua menghasilkan tes hanya untuk parameter yang tidak disetel. Dengan kata lain, jika titik dua dimasukkan, operator menguji keberadaan parameter dan nilainya tidak nol; jika titik dua dihilangkan, operator hanya menguji keberadaannya. Tidak ada bedanya di sini, tetapi baik untuk diketahui.
Palec
17
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 bashset-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
peek@peek:~$ ./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 yang diset = VALID atau tidak disetel / kosong = INVALID.
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}"memperluas ke setjika xdiatur dan ke string kosong jika xtidak disetel).
Untuk memeriksa apakah suatu parameter telah dilewati, uji $#, yang merupakan jumlah parameter yang dilewatkan ke fungsi (atau ke skrip, ketika tidak dalam suatu fungsi) (lihat jawaban Paul ).
Baca bagian "Ekspansi Parameter" pada bashhalaman manual. 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 diset first_argsama dengan $1jika ditugaskan, jika tidak menggunakan nilai "foo". Jika abenar-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 $1contoh ini, keluar saja jika tidak disetel)
Menggunakan [[ -z "$var" ]]adalah cara termudah untuk mengetahui apakah suatu variabel disetel atau tidak, tetapi opsi -zitu tidak membedakan antara variabel yang tidak disetel dan variabel yang disetel ke string kosong:
declare -p: memberi Anda definisi variabel yang diteruskan sebagai parameter. Jika ada, kembalikan 0, jika tidak, kembalikan 1 dan cetak pesan kesalahan.
&> /dev/null: menekan output dari declare -ptanpa mempengaruhi kode pengembaliannya.
Jawaban di atas tidak berfungsi ketika opsi Bash set -udiaktifkan. Juga, mereka tidak dinamis, misalnya, bagaimana 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 1fi# 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.}
Atau Anda bisa melakukannya -ndan tidak meniadakan -z.
Dijeda sampai pemberitahuan lebih lanjut.
1
Anda perlu mengutip sekitar $1, yaitu [ ! -z "$1" ],. Atau Anda dapat menulis [[ ! -z $1 ]]dalam bash / ksh / zsh.
Gilles 'SANGAT berhenti menjadi jahat'
5
Ini akan gagal jika $1diatur ke string kosong.
HelloGoodbye,
4
Cara pilihan saya adalah ini:
$ var=10
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
Jadi pada dasarnya, jika suatu variabel diset, itu menjadi "negasi dari yang dihasilkan false" (apa yang akan true= "diatur").
Dan, jika tidak disetel, itu akan menjadi "negasi dari hasil true" (sebagaimana hasil kosong dievaluasi true) (jadi akan berakhir sebagai false= "TIDAK diatur").
if[[ ${1:+isset}]]then echo "It was set and not null.">&2else echo "It was not set or it was null.">&2fiif[[ ${1+isset}]]then echo "It was set but might be null.">&2else echo "It was was not set.">&2fi
Selamat datang di StackOverflow. Sementara jawaban Anda dihargai, yang terbaik adalah memberikan lebih dari sekadar kode. Bisakah Anda menambahkan alasan untuk jawaban Anda atau penjelasan kecil? Lihat halaman ini untuk ide-ide lain tentang memperluas jawaban Anda.
Celeo
0
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.
Karena Bash 2.0+ Ekspansi tidak langsung tersedia. Anda dapat mengganti panjang dan kompleks (dengan eval juga termasuk) test -n "$(eval "echo "\${${1}+x}"")"untuk yang setara:[[ ${!1+x} ]]
0
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})functionIsDeclared_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 declaredfunctionIsDeclared(){
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
Tes kasus juga menunjukkan bahwa local vartidak TIDAK menyatakan var (kecuali jika diikuti oleh '='). Untuk beberapa waktu saya pikir saya mendeklarasikan variabel dengan cara ini, hanya untuk mengetahui sekarang bahwa saya hanya menyatakan niat saya ... Ini adalah no-op, saya kira.
Saya kebanyakan menggunakan tes ini untuk memberikan (dan mengembalikan) parameter ke fungsi dengan cara yang agak "elegan" dan aman (hampir menyerupai antarmuka ...):
#auxiliary functionsfunction 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 examplefunction 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
tidak akan berfungsi saat Anda memiliki set -uefek yang akan mencetak unboud variablekesalahan
Michael Heuberger
0
Ringkasan
Gunakan test -n "${var-}"untuk memeriksa apakah variabel tidak kosong (dan karenanya harus didefinisikan / ditetapkan juga)
Gunakan test ! -z "${var+}"untuk memeriksa apakah variabel didefinisikan / disetel (meskipun kosong)
Perhatikan bahwa use case pertama jauh lebih umum di skrip shell dan ini adalah apa yang biasanya ingin Anda gunakan.
Catatan
Solusi ini harus bekerja di semua shell POSIX (sh, bash, zsh, ksh, dash)
Beberapa jawaban lain untuk pertanyaan ini benar tetapi mungkin membingungkan bagi orang yang tidak berpengalaman dalam skrip shell, jadi saya ingin memberikan jawaban TLDR yang paling tidak membingungkan bagi orang-orang seperti itu.
Penjelasan
Untuk memahami bagaimana solusi ini bekerja, Anda perlu memahami POSIX testperintah dan perluasan parameter POSIX shell ( spek ), jadi mari kita menutupi dasar-dasar mutlak diperlukan untuk memahami jawabannya.
Perintah tes mengevaluasi ekspresi dan mengembalikan benar atau salah (melalui status keluarnya). Operator -nmengembalikan true jika operan adalah string yang tidak kosong. Jadi misalnya, test -n "a"mengembalikan true, sementara test -n ""mengembalikan false. Sekarang, untuk memeriksa apakah suatu variabel tidak kosong (yang artinya harus didefinisikan), Anda dapat menggunakan test -n "$var". Namun, beberapa skrip shell memiliki set opsi ( set -u) yang menyebabkan referensi apa pun untuk variabel yang tidak terdefinisi untuk memunculkan kesalahan, jadi jika variabel vartidak didefinisikan, ekspresi $aakan menyebabkan kesalahan. Untuk menangani kasus ini dengan benar, Anda harus menggunakan ekspansi variabel, yang akan memberi tahu shell untuk mengganti variabel dengan string alternatif jika tidak ditentukan, menghindari kesalahan yang disebutkan di atas.
Ekspansi variabel ${var-}berarti: jika variabel vartidak terdefinisi (juga disebut "tidak disetel"), ganti dengan string kosong. Jadi test -n "${var-}"akan mengembalikan true jika $vartidak kosong, yang hampir selalu Anda ingin memeriksa skrip shell. Pemeriksaan sebaliknya, jika $vartidak ditentukan atau tidak kosong, akan menjadi test -z "${var-}".
Sekarang untuk use case kedua: memeriksa apakah variabel vardidefinisikan, apakah kosong atau tidak. Ini adalah kasus penggunaan yang kurang umum dan sedikit lebih kompleks, dan saya akan menyarankan Anda untuk membaca jawaban bagus Lionels untuk lebih memahaminya.
Saya pikir maksud Anda set -o nounset, bukan set -o noun set. Ini hanya berfungsi untuk variabel yang telah exportdiedit. Ini juga mengubah pengaturan Anda dengan cara yang aneh untuk dibatalkan.
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
.-v
pengujian mereka , meskipun ini tampaknya hanya tersedia pada versi barubash
dan tidak portabel di seluruh cangkang.Jawaban:
(Biasanya) Cara yang benar
di mana
${var+x}
adalah ekspansi parameter yang mengevaluasi apa-apa jikavar
tidak disetel, dan mengganti stringx
sebaliknya.Kutipan Digresi
Kutipan dapat dihilangkan (jadi kita dapat mengatakan
${var+x}
alih-alih"${var+x}"
) karena sintaks & penggunaan ini menjamin ini hanya akan meluas ke sesuatu yang tidak memerlukan penawaran (karena diperluas kex
(yang tidak mengandung kata istirahat sehingga tidak perlu mengutip), atau untuk tidak ada (yang menghasilkan[ -z ]
, yang dengan mudah mengevaluasi nilai yang sama (benar) yang[ -z "" ]
berlaku juga)).Namun, sementara kutipan dapat dihilangkan dengan aman, dan itu tidak segera jelas bagi semua (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 kutipan sebagai
[ -z "${var+x}" ]
, dengan biaya yang sangat kecil dari 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 mencakup penjelasan mengapa kutipan dapat dihilangkan dengan aman.(Sering) dengan cara yang salah
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-kasus itu
[ -z "$var" ]
akan baik-baik saja.sumber
${var+x}
adalah pengganti yang tepat untuk digunakan. Menggunakan[ -z ${var:+x} ]
tidak menghasilkan hasil yang berbeda dari[ -z "$var" ]
.[ -z "" -a -z ${var+x} ]
Mendapatbash: [: argument expected
bash 4.3-ubuntu (tetapi tidak misalnya zsh). Saya benar-benar tidak suka jawabannya menggunakan sintaks yang kebetulan berfungsi dalam beberapa kasus.[ -z $var ]
tidak lebih "salah" dari menghilangkan tanda kutip. Either way, Anda membuat asumsi tentang input Anda. Jika Anda baik-baik saja memperlakukan string kosong sebagai tidak disetel,[ -z $var ]
itu saja yang Anda butuhkan.Untuk memeriksa variabel string bukan-nol / bukan-nol, yaitu jika disetel, gunakan
Ini kebalikan dari
-z
. Saya menemukan diri saya menggunakan-n
lebih dari-z
.Anda akan menggunakannya seperti:
sumber
[[ ]]
lebih[ ]
, karena[[ ]]
lebih kuat dan menyebabkan masalah kurang dalam situasi tertentu (lihat pertanyaan ini untuk penjelasan tentang perbedaan antara keduanya). Pertanyaannya secara khusus meminta solusi bash dan tidak menyebutkan persyaratan portabilitas.[]
berfungsi lebih baik terutama untuk skrip shell (non-bash).set -u
.-n
ini adalah tes default, jadi lebih sederhana[ "$1" ]
atau[[ $1 ]]
berfungsi juga. Perhatikan juga bahwa dengan[[ ]]
mengutip tidak perlu .Berikut cara menguji apakah parameter tidak disetel , atau kosong ("Null") atau disetel dengan nilai :
Sumber: POSIX: Ekspansi Parameter :
Untuk menunjukkan ini dalam tindakan:
sumber
set foo; echo ${1:-set but null or unset}
echo "foo";set --; echo ${1:-set but null or unset}
gema ditetapkan tetapi nol ...set
:-): ${FOOBAR:=/etc/foobar.conf}
untuk menetapkan nilai default untuk variabel jika tidak disetel atau null.parameter
adalah nama variabel apa saja.word
adalah beberapa string untuk menggantikan tergantung pada sintaksis dalam tabel yang Anda gunakan, dan apakah variabel$parameter
diatur, ditetapkan tetapi null, atau tidak disetel. Bukan untuk membuat hal-hal lebih rumit, tetapiword
juga bisa memasukkan variabel! Ini bisa sangat berguna untuk melewatkan argumen opsional yang dipisahkan oleh karakter. Misalnya:${parameter:+,${parameter}}
menampilkan koma yang dipisahkan,$parameter
jika diset tetapi tidak nol. Dalam hal ini,word
adalah,${parameter}
Sementara sebagian besar teknik yang dinyatakan di sini adalah benar, bash 4.2 mendukung tes aktual untuk kehadiran variabel ( man bash ), daripada menguji nilai variabel.
Khususnya, pendekatan ini tidak akan menyebabkan kesalahan ketika digunakan untuk memeriksa variabel
set -u
/set -o nounset
mode yang tidak disetel , tidak seperti banyak pendekatan lain, seperti menggunakan[ -z
.sumber
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
Ada banyak cara untuk melakukan ini dengan yang berikut ini salah satunya:
Ini berhasil jika $ 1 adalah nol atau tidak disetel
sumber
[[ ]]
hanyalah perangkap portabilitas.if [ -n "$1" ]
harus digunakan di sini.foo=""
,$foo
memiliki nilai, tetapi-z
hanya akan melaporkan bahwa itu kosong. Dan-z $foo
akan meledak jika sudahset -o nounset
.foo=
), maka jawaban Russel benar.Saya selalu menemukan tabel POSIX di jawaban lain lambat untuk grok, jadi inilah pendapat saya:
Perhatikan bahwa setiap kelompok (dengan dan tanpa usus besar sebelumnya) memiliki set dan kasus yang tidak disetel yang sama , jadi satu-satunya hal yang berbeda adalah bagaimana kasus-kasus kosong ditangani.
Dengan usus besar sebelumnya, case kosong dan unset identik, jadi saya akan menggunakan yang mungkin (yaitu penggunaan
:=
, bukan hanya=
, karena case kosong tidak konsisten).Judul:
VARIABLE
non-kosong (VARIABLE="something"
)VARIABLE
kosong / nol (VARIABLE=""
)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 depan.sumber
VARIABLE=""
dapat ditulis sebagaiVARIABLE=
. Namun, yang pertama lebih mudah dibaca.Untuk melihat apakah suatu variabel tidak kosong, saya menggunakan
Tes sebaliknya jika variabel tidak disetel atau kosong:
Untuk melihat apakah suatu variabel disetel (kosong atau kosong), saya menggunakan
Tes sebaliknya jika variabel tidak disetel:
sumber
[ $isMac ] && param="--enable-shared"
${variable+x}
untuk mengaturx
iff$variable
) hampir setengah tahun sebelumnya. Juga memiliki lebih banyak detail menjelaskan mengapa itu benar.${variable+x}
kurang dapat dibaca (& jelas)Pada versi modern Bash (4,2 atau lebih baru, saya pikir; saya tidak tahu pasti), saya akan mencoba ini:
sumber
[ -v "$VARNAME" ]
tidak salah, tetapi cukup lakukan tes yang berbeda. MisalkanVARNAME=foo
; kemudian memeriksa apakah ada variabel bernamafoo
yang disetel.-v
tidak sesuai dengan POSIX[: -v: unexpected operator
, kita harus memastikan untuk menggunakanbash
bukansh
.Meskipun untuk argumen biasanya yang terbaik untuk menguji $ #, yang merupakan jumlah argumen, menurut pendapat saya.
sumber
[ "$1" != "" ]
(atau[ -n "$1" ]
) ...$1
diatur ke string kosong.$1
diatur ke string kosong.set -o nounset
aktif.Catatan
Saya memberikan jawaban yang sangat terfokus pada Bash karena
bash
tag tersebut.Jawaban singkat
Selama Anda hanya berurusan dengan variabel bernama di Bash, fungsi ini harus selalu memberi tahu Anda jika variabel telah ditetapkan, bahkan jika itu adalah array kosong.
Kenapa ini bekerja?
Dalam Bash (setidaknya sejauh 3.0), jika
var
merupakan variabel yang dideklarasikan / ditetapkan, makadeclare -p var
output sebuahdeclare
perintah yang akan mengatur variabelvar
untuk apa pun jenis dan nilainya saat ini, dan mengembalikan kode status0
(sukses). Jikavar
tidak dideklarasikan, kemudiandeclare -p var
menampilkan pesan kesalahan kestderr
dan mengembalikan kode status1
. Menggunakan&>/dev/null
, mengalihkan baik regulerstdout
danstderr
output ke/dev/null
, tidak pernah terlihat, dan tanpa mengubah kode status. Dengan demikian fungsi hanya mengembalikan kode status.Mengapa metode lain (kadang-kadang) gagal di Bash
Ketika metode ini gagal di Bash
Ini hanya bekerja untuk variabel bernama (termasuk
$_
), tidak variabel khusus tertentu ($!
,$@
,$#
,$$
,$*
,$?
,$-
,$0
,$1
,$2
, ..., dan setiap saya mungkin sudah lupa). Karena tidak satupun dari ini adalah array, gaya POSIX[ -n "${var+x}" ]
berfungsi untuk semua variabel khusus ini. Tetapi berhati-hatilah untuk membungkusnya dalam suatu fungsi karena banyak variabel khusus mengubah nilai / keberadaan ketika fungsi dipanggil.Catatan kompatibilitas shell
Jika naskah Anda memiliki array dan Anda mencoba untuk membuatnya kompatibel dengan banyak kerang mungkin, maka pertimbangkan untuk menggunakan
typeset -p
bukandeclare -p
. Saya pernah membaca bahwa ksh hanya mendukung yang pertama, tetapi belum dapat menguji ini. Saya tahu bahwa Bash 3.0+ dan Zsh 5.5.1 masing-masing mendukung keduanya ,typeset -p
dandeclare -p
hanya berbeda satu yang merupakan alternatif untuk yang lain. Tapi saya belum menguji perbedaan di luar dua kata kunci tersebut, dan saya belum menguji shell lain.Jika Anda membutuhkan skrip agar POSIX sh kompatibel, maka Anda tidak dapat menggunakan array. Tanpa array,
[ -n "{$var+x}" ]
berfungsi.Kode perbandingan untuk berbagai metode di Bash
Fungsi ini menghapus variabel
var
,eval
sebagai kode yang diteruskan, menjalankan tes untuk menentukan apakahvar
diatur oleheval
kode d, dan akhirnya menunjukkan kode status yang dihasilkan untuk pengujian yang berbeda.Saya melewatkan
test -v var
,,[ -v var ]
dan[[ -v var ]]
karena mereka menghasilkan hasil yang identik dengan standar POSIX[ -n "${var+x}" ]
, sementara membutuhkan Bash 4.2+. Saya juga melewatkantypeset -p
karena sama sepertideclare -p
di shell saya sudah diuji (Bash 3.0 hingga 5.0, dan Zsh 5.5.1).Kode uji kasus
Perhatikan bahwa hasil tes mungkin tidak terduga karena Bash memperlakukan indeks array non-numerik sebagai "0" jika variabel belum dinyatakan sebagai array asosiatif. Juga, array asosiatif hanya berlaku di Bash 4.0+.
Uji keluaran
Tes mnemonik dalam berkorespondensi baris header untuk
[ -n "$var" ]
,[ -n "${var+x}" ]
,[ "${#var[@]}" != 0 ]
, dandeclare -p var
masing-masing.Ringkasan
sumber
declare -p var &>/dev/null
) adalah SATU-SATUNYA yang berfungsi. TERIMA KASIH!... &> /dev/null
tetapi SO tidak akan membiarkan saya mengedit satu karakter 🙄 (harus> 6 karakter - bahkan mencoba menambah spasi putih tetapi tidak berhasil). Juga, mungkin ada baiknya mengubah fungsi untuk beralih ke$1
variabel bernama sampel (misalnyaOUTPUT_DIR
) karena seperti yang Anda tunjukkan, variabel khusus seperti$1
tidak berfungsi di sini. Bagaimanapun, ini adalah pengeditan yang kritis jika tidak, kode tersebut mencari untuk membuat file yang disebutnull
dalam direktori relatif bernamadev
. BTW - jawaban yang bagus!declare -p PATH &> /dev/null
mengembalikan 0 di mana sebagaideclare -p ASDFASDGFASKDF &> /dev/null
pengembalian 1. (pada bash 5.0.11 (1) -release)declare var
menyatakan var variabel tetapi tidak mengaturnya dalam halset -o nounset
: Uji dengandeclare foo bar=; set -o nounset; echo $bar; echo $foo
/
! Saya memperbaikinya, tapi saya pikir logikanya cukup membingungkan untuk menjamin suatu fungsi, terutama mengingat komentar @ xebeche. @ xebeche Itu tidak nyaman untuk jawaban saya.… Sepertinya saya harus mencoba sesuatu sepertideclare -p "$1" | grep =
atautest -v "$1"
.Bagi mereka yang ingin memeriksa tidak disetel atau kosong ketika dalam skrip dengan
set -u
:Pemeriksaan reguler
[ -z "$var" ]
akan gagalvar; unbound variable
jikaset -u
tetapi[ -z "${var-}" ]
berkembang menjadi string kosong jikavar
tidak disetel tanpa gagal.sumber
${var:-}
tidak${var-}
. Tapi di Bash, saya bisa memastikan itu berfungsi bahkan tanpa tanda titik dua.${var:-}
dan${var-}
berarti hal yang berbeda.${var:-}
akan diperluas ke string kosong jikavar
tidak disetel atau null dan${var-}
akan diperluas ke string kosong hanya jika tidak disetel.Anda ingin keluar jika tidak disetel
Ini berhasil untuk saya. Saya ingin skrip saya keluar dengan pesan kesalahan jika parameter tidak disetel.
Ini kembali dengan kesalahan saat dijalankan
Periksa saja, tidak ada jalan keluar - Kosong dan Tidak diset adalah INVALID
Coba opsi ini jika Anda hanya ingin memeriksa apakah nilai yang diset = VALID atau tidak disetel / kosong = INVALID.
Atau, Bahkan tes singkat ;-)
Periksa saja, tidak ada jalan keluar - Hanya kosong yang tidak valid
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)
Tes singkat
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
sumber
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}"
memperluas keset
jikax
diatur dan ke string kosong jikax
tidak disetel).Untuk memeriksa apakah suatu parameter telah dilewati, uji
$#
, yang merupakan jumlah parameter yang dilewatkan ke fungsi (atau ke skrip, ketika tidak dalam suatu fungsi) (lihat jawaban Paul ).sumber
Baca bagian "Ekspansi Parameter" pada
bash
halaman manual. 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:
akan diset
first_arg
sama dengan$1
jika ditugaskan, jika tidak menggunakan nilai "foo". Jikaa
benar-benar harus mengambil parameter tunggal, dan tidak ada default yang baik, Anda dapat keluar dengan pesan kesalahan ketika tidak ada parameter yang diberikan:(Perhatikan penggunaan
:
sebagai perintah nol, yang hanya memperluas nilai argumennya. Kami tidak ingin melakukan apa pun dengan$1
contoh ini, keluar saja jika tidak disetel)sumber
: ${var?message}
.Dalam bash, Anda dapat menggunakan
-v
di dalam[[ ]]
builtin:sumber
Menggunakan
[[ -z "$var" ]]
adalah cara termudah untuk mengetahui apakah suatu variabel disetel atau tidak, tetapi opsi-z
itu tidak membedakan antara variabel yang tidak disetel dan variabel yang disetel ke string kosong:Cara terbaik untuk memeriksanya sesuai dengan jenis variabel: variabel env, parameter atau variabel biasa.
Untuk variabel env:
Untuk parameter (misalnya, untuk memeriksa keberadaan parameter
$5
):Untuk variabel reguler (menggunakan fungsi bantu, lakukan dengan cara yang elegan):
Catatan:
sumber
Jawaban di atas tidak berfungsi ketika opsi Bash
set -u
diaktifkan. Juga, mereka tidak dinamis, misalnya, bagaimana menguji variabel dengan nama "dummy" didefinisikan? Coba ini:Terkait: Di Bash, bagaimana saya menguji jika variabel didefinisikan dalam mode "-u"
sumber
eval "[ ! -z \${$1:-} ]"
evaluasi tidak langsung:[ ! -z ${!1:-} ];
.Anda dapat melakukan:
sumber
-n
dan tidak meniadakan-z
.$1
, yaitu[ ! -z "$1" ]
,. Atau Anda dapat menulis[[ ! -z $1 ]]
dalam bash / ksh / zsh.$1
diatur ke string kosong.Cara pilihan saya adalah ini:
Jadi pada dasarnya, jika suatu variabel diset, itu menjadi "negasi dari yang dihasilkan
false
" (apa yang akantrue
= "diatur").Dan, jika tidak disetel, itu akan menjadi "negasi dari hasil
true
" (sebagaimana hasil kosong dievaluasitrue
) (jadi akan berakhir sebagaifalse
= "TIDAK diatur").sumber
Atau
Atau
Atau
sumber
Dalam sebuah shell Anda dapat menggunakan
-z
operator yang Benar jika panjang string adalah nol.Satu
MY_VAR
garis sederhana untuk menetapkan default jika tidak disetel, jika tidak, Anda dapat menampilkan pesan:sumber
sumber
$1
,$2
dan hingga$N
selalu diatur. Maaf, ini gagal.Saya menemukan (banyak) kode yang lebih baik untuk melakukan ini jika Anda ingin memeriksa apa pun di
$@
.Kenapa ini semua? Semua yang
$@
ada di Bash, tetapi secara default kosong, jaditest -z
dantest -n
tidak dapat membantu Anda.Pembaruan: Anda juga dapat menghitung jumlah karakter dalam suatu parameter.
sumber
sumber
Inilah yang saya gunakan setiap hari:
Ini berfungsi dengan baik di Linux dan Solaris hingga bash 3.0.
sumber
test -n "$(eval "echo "\${${1}+x}"")"
untuk yang setara:[[ ${!1+x} ]]
Saya suka fungsi bantu untuk menyembunyikan detail kasar bash. Dalam hal ini, melakukannya menambah lebih banyak kekasaran (tersembunyi):
Karena saya pertama kali memiliki bug dalam implementasi ini (terinspirasi oleh jawaban Jens dan Lionel), saya datang dengan solusi yang berbeda:
Saya merasa lebih lurus ke depan, lebih malu dan lebih mudah dipahami / diingat. Uji kasus menunjukkan itu setara:
Tes kasus juga menunjukkan bahwa
local var
tidak TIDAK menyatakan var (kecuali jika diikuti oleh '='). Untuk beberapa waktu saya pikir saya mendeklarasikan variabel dengan cara ini, hanya untuk mengetahui sekarang bahwa saya hanya menyatakan niat saya ... Ini adalah no-op, saya kira.BONUS: usecase
Saya kebanyakan menggunakan tes ini untuk memberikan (dan mengembalikan) parameter ke fungsi dengan cara yang agak "elegan" dan aman (hampir menyerupai antarmuka ...):
Jika dipanggil dengan semua, variabel harus dideklarasikan:
lain:
sumber
Setelah membaca semua jawaban, ini juga berfungsi:
jika Anda tidak meletakkan
SOME_VAR
apa yang saya miliki$SOME_VAR
, itu akan menetapkannya ke nilai kosong;$
diperlukan untuk ini berfungsi.sumber
set -u
efek yang akan mencetakunboud variable
kesalahanRingkasan
test -n "${var-}"
untuk memeriksa apakah variabel tidak kosong (dan karenanya harus didefinisikan / ditetapkan juga)test ! -z "${var+}"
untuk memeriksa apakah variabel didefinisikan / disetel (meskipun kosong)Perhatikan bahwa use case pertama jauh lebih umum di skrip shell dan ini adalah apa yang biasanya ingin Anda gunakan.
Catatan
Penjelasan
Untuk memahami bagaimana solusi ini bekerja, Anda perlu memahami POSIX
test
perintah dan perluasan parameter POSIX shell ( spek ), jadi mari kita menutupi dasar-dasar mutlak diperlukan untuk memahami jawabannya.Perintah tes mengevaluasi ekspresi dan mengembalikan benar atau salah (melalui status keluarnya). Operator
-n
mengembalikan true jika operan adalah string yang tidak kosong. Jadi misalnya,test -n "a"
mengembalikan true, sementaratest -n ""
mengembalikan false. Sekarang, untuk memeriksa apakah suatu variabel tidak kosong (yang artinya harus didefinisikan), Anda dapat menggunakantest -n "$var"
. Namun, beberapa skrip shell memiliki set opsi (set -u
) yang menyebabkan referensi apa pun untuk variabel yang tidak terdefinisi untuk memunculkan kesalahan, jadi jika variabelvar
tidak didefinisikan, ekspresi$a
akan menyebabkan kesalahan. Untuk menangani kasus ini dengan benar, Anda harus menggunakan ekspansi variabel, yang akan memberi tahu shell untuk mengganti variabel dengan string alternatif jika tidak ditentukan, menghindari kesalahan yang disebutkan di atas.Ekspansi variabel
${var-}
berarti: jika variabelvar
tidak terdefinisi (juga disebut "tidak disetel"), ganti dengan string kosong. Jaditest -n "${var-}"
akan mengembalikan true jika$var
tidak kosong, yang hampir selalu Anda ingin memeriksa skrip shell. Pemeriksaan sebaliknya, jika$var
tidak ditentukan atau tidak kosong, akan menjaditest -z "${var-}"
.Sekarang untuk use case kedua: memeriksa apakah variabel
var
didefinisikan, apakah kosong atau tidak. Ini adalah kasus penggunaan yang kurang umum dan sedikit lebih kompleks, dan saya akan menyarankan Anda untuk membaca jawaban bagus Lionels untuk lebih memahaminya.sumber
Untuk memeriksa apakah var diatur atau tidak
sumber
$var
diatur ke string kosong.Jika Anda ingin menguji apakah suatu variabel terikat atau tidak terikat, ini berfungsi dengan baik, bahkan setelah Anda mengaktifkan opsi nounset:
sumber
set -o nounset
, bukanset -o noun set
. Ini hanya berfungsi untuk variabel yang telahexport
diedit. Ini juga mengubah pengaturan Anda dengan cara yang aneh untuk dibatalkan.