skrip bash [x $ 1 = x]

21

Saya membaca skrip bash, saya tidak mengerti apa yang sedang terjadi di sana.

#!/bin/sh
[ x$1 = x ] 

Apa yang terjadi pada baris kedua dan apa [ x$1 = x ] artinya?

Bob
sumber

Jawaban:

27

Itu memeriksa yang $1kosong, meskipun harus dikutip (identik dengan [ -z "$1" ]). Beberapa cangkang yang sangat tua tidak menangani string kosong dengan benar, sehingga penulis skrip portabel mengadopsi gaya pemeriksaan ini. Itu tidak perlu selama beberapa dekade, tetapi orang masih melakukannya dengan cara itu karena orang masih melakukannya dengan cara itu.

Kevin
sumber
Ya, Anda seharusnya tidak melakukannya seperti ini lagi dan mengadopsi gaya yang lebih modern. Kecuali Anda sedang mengerjakan PDP11.
MacLemon
4
Ini bukan tentang string kosong. [ x$1 = x ]masih salah, tapi [ "x$1" = x ]akan kerang yang memiliki masalah di mana $1adalah !atau (atau -n.... [ "" = "$1" ]dan case $1 in "")juga akan OK sekalipun.
Stéphane Chazelas
2
@ MacLemon, tidak perlu pergi sejauh itu. [ -z "$1" ]dan [ "$1" = "" ]masih tidak berfungsi dengan / bin / sh dari Solaris 10, yang pertama dengan dash-0.5.4.
Stéphane Chazelas
1
ekstra +1 untuk kalimat terakhir!
glenn jackman
1
@glennjackman, kalimat terakhir itu salah. Solaris 10 masih merupakan versi yang paling banyak digunakan dari Solaris dan [ "$1" = "" ]masih tidak berfungsi dengan itu /bin/sh(meskipun Anda ingin menggunakannya di /usr/xpg4/bin/shsana, tidak /bin/sh). dasbor diperbaiki dalam hal itu pada Januari 2009.
Stéphane Chazelas
8

Kurung kotak menunjukkan tes , jadi [ x$1 = x]tanpa ifatau yang serupa tidak ada artinya, meskipun secara sintaksis ok.

Ini dimaksudkan untuk mengevaluasi ke true jika x$1diperluas ke x, dan salah sebaliknya, tetapi karena tidak dikutip, jika $1(misalnya) "hey x", shell akan melihat x = x, jadi konstruksi ini masih tidak aman.

Tujuan x = xpemeriksaan adalah untuk menentukan apakah suatu variabel kosong. Cara yang lebih umum untuk melakukan ini adalah dengan hanya menggunakan tanda kutip:

if [ "$1" = "" ]; then

Operator uji Bash -zdan -njuga dapat digunakan, tetapi mereka kurang portabel untuk jenis shell lainnya. 1

Alasan untuk kutipan, atau x$1, adalah agar sisi kiri tidak berkembang menjadi apa-apa, yang akan menjadi kesalahan sintaksis:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. Sebenarnya, testbisa menjadi utilitas mandiri tetapi sebagian besar shell mengimplementasikannya sebagai built-in; periksa perbedaan antara which testdan type test. Pada GNU / Linux man testklaim untuk merujuk pada built-in, tetapi jika Anda menelepon (misalnya) /usr/bin/test, utilitas itu tampaknya mengimplementasikan fitur-fitur yang didokumentasikan dalam halaman manual, termasuk -zdan -n.

goldilocks
sumber
1
[ x$1 = x ]juga akan mengevaluasi true jika $1misalnya " -o x". Coba sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]salah dan tidak masuk akal.
Stéphane Chazelas
@ StéphaneChazelas Terima kasih SC - diedit (para ke-2).
goldilocks
Anda tidak perlu ifmenggunakan test, Anda dapat menggunakannya sebelum &&, ||atau setelah whileatau memeriksa hasilnya menggunakan$?
Jasen
8
[ x$1 = x ]

Masuk akal zsh. Itu membandingkan gabungan darix dengan argumen pertama dari skrip x. Jadi [perintah mengembalikan true jika $1kosong atau tidak disediakan.

[ $1 = "" ]

Tidak akan bekerja karena, zshketika sebuah variabel kosong tidak dikutip dalam konteks daftar, ia tidak memperluas argumen sama sekali alih-alih argumen kosong, jadi jika $1tidak disetel atau kosong, [perintah hanya akan menerima sebagai argumen [, =string kosong dan ]itu tidak masuk akal. [ -z "$1" ]atau [ "$1" = "" ]akan baik-baik saja seperti di shell POSIX.

Dalam cangkang Bourne-like / POSIX, [ x$1 = x ]tidak masuk akal. Itulah operator split + glob yang entah bagaimana diterapkan pada rangkaian xdan argumen pertama dari skrip yang berharap bahwa hasilnya dan =dan x, dan ]membuat ekspresi pengujian yang valid untuk [perintah tersebut.

Misalnya, jika skrip disahkan satu " = x -o x ="argumen, [akan menerima argumen mereka: [, x, =, x, -o, x, =, x, ], yang [akan mengerti sebagai membandingkan xdengan xdan xdengan xdan kembali benar.

Jika $1ada "* *", maka shell akan meneruskan ke [perintah daftar file di direktori saat ini yang namanya dimulai denganx (perluasan segumpal x*), maka daftar file non-tersembunyi (ekspansi *) ... yang [tidak mungkin untuk dapat masuk akal dari. Satu-satunya kasus di mana itu akan melakukan sesuatu yang masuk akal adalah jika $1tidak mengandung karakter pengganti atau karakter kosong.

Sekarang, apa yang kadang Anda temukan adalah kode seperti:

[ "x$1" = x ]

Itu digunakan untuk menguji apakah $1kosong atau tidak disetel.

Cara normal untuk menguji variabel kosong atau tidak disetel adalah:

[ -z "$1" ]

Tapi itu gagal untuk beberapa nilai $1seperti =di beberapa (non-POSIX) [implementasi seperti yang dibangun di shell Bourne seperti yang ditemukan /bin/shpada Solaris 10 dan sebelum atau beberapa versi lama dash(hingga 0,5,4) atau shbeberapa BSD.

Itu karena [melihat [, -z, =, ]dan mengeluh tentang hilang argumen ke =operator biner bukan pemahaman itu sebagai -zunary operator diterapkan pada =tali.

Demikian pula, [ "$1" = "" ]gagal karena beberapa implementasi dari [jika $1ini !atau (.

Dalam shell / [implementasi tersebut:

[ "x$1" = x ]

selalu merupakan tes yang valid terlepas dari nilai $1, demikian juga:

[ "" = "$1" ]

dan:

[ -z "${1:+x}" ]

dan

case $1 in "") ...; esac

Tentu saja, jika Anda ingin memeriksa bahwa tidak ada argumen yang diberikan, Anda akan melakukannya:

[ "$#" -eq 0 ]

Artinya, Anda memeriksa jumlah argumen yang diteruskan ke skrip.

Perhatikan bahwa saat ini, [ -z "$var" ]jelas ditentukan oleh POSIX dan tidak bisa gagal dalam conformant [implementasi (dan bash's [adalah dan telah selama beberapa dekade). Jadi, Anda harus dapat mengandalkannya dalam POSIX sh atau bashskrip.

Stéphane Chazelas
sumber
0

x$1adalah gabungan dua string xdan $1dan jika $ 1 kosong, x $ 1 sama dengan x, dan [x $ 1 = x] akan menjadi benar sebagai hasilnya. x = ydigunakan untuk membandingkan string dalam sh

harish.venkat
sumber
2
Tidak x$1tidak dikutip, jadi pemecahan dan penggumpalan dilakukan pada mereka.
Stéphane Chazelas
0

[ x$1 = x ]benar jika $1tidak disetel / null / kosong atau tidak.
Coba sendiri dengan:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
dan
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"

xx4h
sumber
1
[ x$1 = x ]juga benar jika $1misalnya " -o x". Coba sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]salah dan tidak masuk akal.
Stéphane Chazelas