Dalam dokumentasi Perl, perlrun (1) menyarankan meluncurkan skrip Perl menggunakan header bilingual shell / Perl:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
Apa ${1+"$@"}
artinya Saya mencoba menggunakan "$@"
sebagai gantinya (menggunakan Bash sebagai / bin / sh), dan sepertinya berfungsi juga.
Sunting
Dua jawaban di bawah mengatakan bahwa memang seharusnya begitu ${1:+"$@"}
. Saya mengetahui ${parameter:+word}
sintaks ("Gunakan Nilai Alternatif") yang didokumentasikan dalam bash (1). Namun, saya tidak yakin, karena
Keduanya
${1+"$@"}
dan"$@"
berfungsi dengan baik, bahkan ketika tidak ada parameter. Jika saya membuat simple.sh sebagai#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
dan question.sh sebagai
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
Saya bisa membuat keduanya bekerja secara identik:
$ ./question.sh $VAR1 = []; $ ./question.sh a $VAR1 = [ 'a' ]; $ ./question.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./question.sh "" $VAR1 = [ '' ]; $ ./simple.sh $VAR1 = []; $ ./simple.sh a $VAR1 = [ 'a' ]; $ ./simple.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./simple.sh "" $VAR1 = [ '' ];
Sumber lain di Internet juga menggunakan
${1+"$@"}
, termasuk satu peretas yang tampaknya tahu apa yang dia lakukan.
Mungkin ${parameter+word}
sintaks alternatif (atau tidak digunakan) yang tidak didokumentasikan ${parameter:+word}
? Bisakah seseorang mengkonfirmasi hipotesis itu?
Jawaban:
Itu untuk kompatibilitas dengan shell Bourne. Cangkang Bourne adalah cangkang tua yang pertama kali dirilis dengan Unix versi 7 pada tahun 1979 dan masih umum sampai pertengahan 90-an seperti
/bin/sh
pada kebanyakan Unix komersial.Ini adalah leluhur dari sebagian besar kerang mirip Bourne seperti
ksh
,bash
atauzsh
.Itu memiliki beberapa fitur canggung banyak yang telah diperbaiki
ksh
dan kerang lainnya dan spesifikasi standar barush
, salah satunya adalah ini:Dengan shell Bourne (setidaknya varian yang belum diperbaiki):
"$@"
perluas satu argumen kosong jika daftar parameter posisi kosong ($# == 0
) alih-alih tidak ada argumen sama sekali.${var+something}
meluas ke "sesuatu" kecuali$var
tidak disetel. Itu jelas didokumentasikan dalam semua shell tetapi sulit ditemukan dalambash
dokumentasi karena Anda perlu memperhatikan kalimat ini:Jadi
${1+"$@"}
mengembang"$@"
hanya jika$1
diatur ($# > 0
) yang bekerja di sekitar batasan shell Bourne.Perhatikan bahwa cangkang Bourne adalah satu-satunya cangkang dengan masalah itu. Modern
sh
(yangsh
sesuai dengan spesifikasi POSIXsh
(yang tidak dimiliki shell Bourne)) tidak memiliki masalah itu. Jadi Anda hanya perlu itu jika Anda memerlukan kode Anda untuk bekerja pada sistem yang sangat lama di mana/bin/sh
mungkin shell Bourne bukan shell standar (perhatikan bahwa POSIX tidak menentukan lokasi standarsh
, jadi misalnya pada Solaris sebelum Solaris 11,/bin/sh
masih merupakan shell Bourne (meskipun tidak memiliki masalah tertentu) sementara yang normal / standarsh
berada di lokasi lain (/usr/xpg4/bin/sh
)).Namun ada masalah di
perlrun
halaman perldoc yang$0
tidak dikutip.Lihat http://www.in-ulm.de/~mascheck/various/bourne_args/ untuk informasi lebih lanjut.
sumber
Ada perbedaan antara:
dan
Dalam satu, Anda melewati satu argumen yang merupakan string kosong. Dalam yang kedua, ada nol argumen yang disahkan.
Untuk kedua, "$ @" akan sama dengan hal yang sama:
""
. Tetapi menggunakan${1:+"$@"}
akan""
untuk yang pertama dan tidak ada argumen yang berlalu untuk yang kedua, yang merupakan maksud.Ini menjadi penting jika Anda melakukan sesuatu skrip di bawah ini, yang disebut sshwrapper, yang Anda panggil dengan perintah opsional atau tanpa argumen untuk mendapatkan shell interaktif.
Ini akan mencoba menjalankan "" pada host jarak jauh (yang baru saja mengembalikan), itu tidak akan menjadi shell interaktif.
Akan memulai shell interaktif pada host jarak jauh karena exec akan benar menafsirkan variabel sebagai bukan apa-apa, bukan string kosong.
Baca penggunaan "$ {parameter: + word}" ("Gunakan Nilai Alternatif") dan string ekspansi variabel serupa di halaman manual bash.
sumber
sh
implementasi POSIX-conformant (lihat jawaban lain).${1:+"$@"}
akan diperluas ke tidak ada argumen jika$1
kosong. Kamu ingin${1+"$@"}
. Pada dasarnya Anda memilikinya terbalik.Saya merangkum jawaban Stéphane Chazelas:
jadi jika menggunakan yang kedua dengan parameter "", itu berarti $ 1 adalah nol, tetapi itu tidak menguji apakah itu nol atau tidak, itu hanya melihat itu sudah diatur tetapi tetap kosong atau tidak, sehingga akan memperluas $ @ , tetapi Anda menggunakan $ {1: + "$ @"} 'dengan "", itu tidak akan berkembang
$@
lagi.sumber