Saya baru saja menemukan beberapa jawaban seperti mem-parsing file teks yang dibatasi ... yang menggunakan konstruk:
while IFS=, read xx yy zz;do
echo $xx $yy $zz
done < input_file
di mana IFS
variabel diatur sebelum read
perintah.
Saya telah membaca referensi bash tetapi tidak tahu mengapa ini legal.
Saya mencoba
$ x="once upon" y="a time" echo $x $y
dari prompt perintah bash tetapi tidak mendapatkan apa-apa. Dapatkah seseorang mengarahkan saya ke tempat sintaks didefinisikan dalam referensi yang memungkinkan variabel IFS diatur dengan cara itu? Apakah ini kasus khusus atau dapatkah saya melakukan sesuatu yang serupa dengan variabel lain?
bash
shell
environment-variables
Mike Lippert
sumber
sumber
Jawaban:
Itu di bawah Shell Grammar, Simple Commands (penekanan ditambahkan):
Jadi, Anda dapat melewati variabel apa pun yang Anda inginkan. Anda
echo
misalnya tidak bekerja karena variabel dilewatkan ke perintah, tidak diatur dalam shell. Shell mengembang$x
dan$y
sebelum menjalankan perintah. Ini berfungsi, misalnya:sumber
man bash
di sistem saya ...Variabel yang didefinisikan menjadi seperti variabel lingkungan pada proses bercabang.
Jika Anda berlari
kemudian bash pertama-tama mengembang
$A
ke""
dan kemudian berjalanInilah cara yang benar:
Perhatikan tanda kutip tunggal di
bash -c
, jika tidak, Anda memiliki masalah yang sama seperti di atas.Jadi contoh loop Anda legal karena perintah bash builtin 'read' akan mencari IFS dalam variabel lingkungannya, dan menemukannya
,
. Karena itu,akan dicetak
TEST is and I is test
Terakhir, seperti untuk sintaks, dalam for loop, sebuah string diharapkan. Karena itu saya harus menggunakan backticks untuk membuatnya menjadi sebuah perintah. Namun, sementara loop mengharapkan sintaks perintah, seperti
IFS=, read xx yy zz
.sumber
A
bash variabel yang tidak disetel diperluas$A
ke string kosong tetapi untuk menghindari kebingungan saya tidak akan menggunakan""
karena kode tersebut tidak setara denganA="b" echo ""
. Tidak akan ada argumen untukecho
.man bash
Variabel diperluas sebelum penugasan variabel berlangsung. Untuk alasan yang jelas itu
var=x
akan bekerja sebaliknya, tetapivar=$othervar
tidak mau. Yaitu, Anda$x
diperlukan sebelum tersedia. Tapi itu bukan masalah utama. Masalah utama adalah bahwa baris perintah dapat dimodifikasi oleh lingkungan shell saja tetapi penugasan tidak menjadi bagian dari lingkungan shell.Anda mencampuradukkan fitur: Anda menginginkan penggantian baris perintah tetapi memasukkan definisi variabel ke dalam lingkungan perintah. Penggantian baris perintah harus dilakukan oleh shell. Lingkungan harus secara eksplisit digunakan oleh perintah yang dipanggil. Apakah dan bagaimana ini dilakukan tergantung pada perintah.
Keuntungan dari penggunaan ini adalah Anda dapat mengatur lingkungan untuk subproses tanpa mempengaruhi lingkungan shell.
berfungsi seperti yang Anda harapkan karena dalam hal ini kedua fitur digabungkan: Penggantian baris perintah tidak dilakukan oleh shell panggilan tetapi oleh shell subprocess.
sumber
x="once upon" y="a time" eval 'echo $x $y'
ketika tidak ada subproses karenaeval
merupakan builtin. Saya kira kutipan yang relevan dari manual ini adalahThe environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments
. Mempertimbangkan contoh pertanyaan itu harus seperti ini karenaread
juga builtin dan bekerja dengan keadaan sementara yang berubahIFS
.Perintah yang Anda berikan adalah berbeda karena
$x
dan$y
diperluas sebelum ituecho
perintah berjalan, sehingga nilai-nilai mereka di saat shell yang digunakan, bukan nilai-nilai yangecho
akan Anda lihat di lingkungannya jika ingin terlihat.sumber
x
dany
untuk lingkungan yangecho
berjalan, bukan lingkungan di mana argumen untukecho
diperluas. SebabIFS=, read xx yy zz
, seluruh string dibaca, tidak terbuka, denganread
perintah. Kemudian , string yang dibagi sesuai dengan nilaiIFS
, dengan potongan yang sesuai ditugaskan untukxx
,yy
, danzz
.bash
pertama mem-parsing baris perintah yang diberikan, mengakui bahwa ada dua tugas variabel untuk diterapkan pada lingkungan perintah yang akan datang, mengidentifikasi perintah untuk menjalankan (echo
), memperluas parameter yang ditemukan dalam argumen, kemudian menjalankan perintahecho
dengan argumen yang diperluas.echo
saya tidak yakin apakah itu bisa "melihat" variabel, karena itu adalah perintah builtin dan karena itu tidak berjalan dalam subkulit yang bisa memiliki lingkungan sendiri. Tapi saya mencobanya denganeval
yang juga merupakan builtin dan memang tahu tentang itu. Misalnya cobaa=xyz eval 'echo $BASHPID $a; grep -z ^a /proc/$BASHPID/{,task/*}/environ'; echo $BASHPID $a
yang menunjukkan bahwaa
hanya diatur di dalameval
meskipun pid adalah sama dan lingkungan tidak berubah selama eval! (Untuk mengakses/proc
Anda perlu menjalankan ini di Linux.) Sepertinya bash melakukan beberapa sihir tambahan di sini.Saya akan melihat gambaran yang lebih besar tentang " mengapa ini legal"
Jawab: Agar Anda dapat memanggil atau menjalankan program dan untuk pemanggilan itu hanya menggunakan variabel dengan variabel tertentu.
Sebagai contoh: Anda memiliki param untuk koneksi basis data yang disebut 'db_connection', dan biasanya Anda meneruskan 'test' sebagai nama untuk koneksi basis data pengujian Anda. Bahkan Anda bahkan dapat menetapkannya sebagai default yang tidak perlu Anda lewati secara eksplisit. Namun terkadang Anda ingin bekerja dengan database ci. Jadi Anda lulus dalam param sebagai 'ci' dan kemudian program yang disebut menggunakan yang param database sebagai nama db digunakan untuk semua panggilan database. Untuk menjalankan selanjutnya, jika Anda tidak mengulangi pendekatan dan hanya memanggil program variabel akan kembali ke nilai default sebelumnya.
sumber
Anda juga bisa menggunakan
;
. Ini akan dievaluasi sebelumnya karena itu pemisah perintah.sumber