Memperluas jawaban (saat ini diterima) dari redneb...
TL;DR Perlu sumber skrip tanpa argumen posisi dalam skrip lain ? coba function DoSource() { source test.sh ; } ; DoSource
bukan hanya source test.sh
.
source
membuat skrip tanpa argumen di dalam skrip lain
Kutipan dari Bash manual dalam pertanyaan menunjukkan detail tentang bagaimana parameter posisi ditetapkan ke skrip bersumber. Khususnya, jika perintah sumber tidak menentukan argumen apa pun , ini ditetapkan dari lingkungan pemanggilan.
Konsekuensinya adalah mungkin merepotkan untuk source
skrip tidak memberikan argumen dalam skrip lain. Misalnya, mari gunakan contoh redneb sebagai test.sh
:
echo "I was given $# argument(s):"
printf "%s\n" "[email protected]"
bersumber dari skrip lain userScript.sh
, yaitu mis. satu kalimat:
source test.sh
Saat menjalankan contoh seperti di atas:
$ bash userScript.sh a 'b c'
I was given 2 argument(s):
a
b c
test.sh
mewarisi userScript.sh
argumen posisi ... yang sekarang bukan yang saya inginkan (jika saya melakukannya, saya bisa menggunakan source test.sh "[email protected]"
).
Saya telah menemukan yang berikut sebagai solusi yang berguna:merangkum perintah sumber ke dalam fungsi Bash. userScript.sh
baru terlihat seperti:
function DoSource() { source test.sh ; }
DoSource
laporan:
$ bash userScript.sh a 'b c'
I was given 0 argument(s):
Perhatikan bahwa menentukan argumen kosong (source test.sh ''
) tidak setara, karena argumen kosong akan diteruskan ke test.sh
.
Jika skrip sumber juga diharapkan bersumber
Jika userScript.sh
sendiri seharusnya bersumber, maka orang mungkin tidak ingin meninggalkan DoSource()
sekitar. Dalam hal ini, solusi sederhananya adalah penghancuran diri:
function _userScript_sh_DoSource() { source test.sh ; unset "$FUNCNAME" ; }
_userScript_sh_DoSource
untuk penggunaan sekali saja (nama fungsi telah dipilih untuk mengurangi kemungkinan konflik nama); atau unset _userScript_sh_DoSource
perintah dapat ditempatkan setelah _userScript_sh_DoSource
tidak diperlukan lagi.
Varian fleksibel untuk beberapa penggunaan
Varian yang lebih kompleks dari DoSource()
:
function DoSource() { local ScriptName="$1" ; shift ; source "$ScriptName" ; }
DoSource test1.sh
DoSource test1.sh "[email protected]"
DoSource test2.sh
dapat digunakan sebagai pengganti "drop-in" untuk source
, dengan satu-satunya perbedaan adalah ketika tidak ada argumen posisi yang ditentukan untuk sumber skrip, source
mewarisinya, sedangkan DoSource
tidak menggunakan apapun. Perhatikan bahwa DoSource
adalah fungsi dan dengan demikian berperilaku berbeda dari source
dalam aspek lain (misalnya stack call, FUNCNAME
, ...).
Buat file test.sh
dengan isi sebagai berikut:
echo "I was given $# argument(s):"
printf "%s\n" "[email protected]"
dan kemudian mengambilnya dari sesi shell interaktif:
$ source ./test.sh a 'b c'
I was given 2 argument(s):
a
b c
jadi Anda mengakses argumen seperti yang Anda lakukan di skrip bash biasa, dengan [email protected]
atau $1
, $2
, $3
, dll.
Sebagai perbandingan, jalankan sebagai skrip biasa:
$ bash ./test.sh a 'b c'
I was given 2 argument(s):
a
b c