Begini saran saya, Anda harus melakukannya, dan saya akan menjelaskan alasannya, tetapi pertama-tama saya ingin berbicara tentang sesuatu yang lain ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
Banyak solusi disodorkan lain di sini tampaknya menyarankan bahwa Anda entah bagaimana dapat mempengaruhi konten variabel shell dengan mengubah metode Anda memperluasnya. Saya dapat meyakinkan Anda bahwa ini bukan masalahnya.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
KELUARAN
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
Apa yang Anda lihat di atas adalah pertama ekspansi field-split, kemudian laporan tentang byte-count untuk variabel sumber ekspansi, kemudian ekspansi yang dibatasi-kuotasi, dan byte-count yang sama. Sementara output mungkin berbeda, isi variabel shell $string
tidak pernah berubah sama sekali kecuali pada penugasan.
Terlebih lagi, jika Anda tidak mengerti mengapa ini terjadi, Anda pasti akan menghadapi beberapa kejutan yang sangat buruk lebih cepat daripada nanti. Mari kita coba lagi, tetapi dalam kondisi yang sedikit berbeda.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
Sama $string
- lingkungan berbeda.
KELUARAN
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
Pemecahan bidang terjadi berdasarkan pembatas bidang yang didefinisikan dalam $IFS
. Ada dua jenis pembatas - $IFS
spasi putih dan yang $IFS
lainnya. Secara default $IFS
ditugaskan baris ruang nilai tab - yang merupakan tiga kemungkinan $IFS
nilai ruang kosong. Namun, ini mudah diubah, seperti yang Anda lihat di atas, dan dapat memiliki efek drastis pada ekspansi bidang-split.
$IFS
spasi putih akan berurutan dengan urutan ke bidang tunggal - dan inilah sebabnya echo
ekspansi yang berisi urutan ruang mana pun ketika $IFS
berisi ruang akan mengevaluasi hanya ruang tunggal - karena echo
menyatukan argumennya pada ruang. Tetapi nilai-nilai non-spasi putih tidak akan hilang dengan cara yang sama, dan setiap pembatas yang terjadi selalu mendapatkan bidang untuk dirinya sendiri - seperti yang dapat dilihat pada perluasan barang di atas.
Ini bukan yang terburuk. Pertimbangkan yang lain ini $string
.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
KELUARAN
* * * * * * 30
* * * * * * 30
Terlihat oke, bukan? Baiklah, mari kita ubah lingkungan lagi.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
KELUARAN
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
Wow.
Secara default shell akan memperluas nama file jika itu bisa cocok dengan mereka. Ini terjadi setelah ekspansi parameter dan pemisahan bidang dalam urutan parse-nya dan sehingga string yang tidak dikutip dikutip rentan dengan cara ini. Anda dapat menonaktifkan perilaku ini set -f
jika Anda suka, tetapi setiap shell yang kompatibel dengan POSIX akan selalu menggumpal secara default.
Ini adalah jenis hal yang Anda hadapi ketika Anda memberikan tanda kutip pada ekspansi yang sesuai dengan preferensi indentasi Anda. Dan meskipun demikian, dalam setiap kasus, terlepas dari perilaku ekspansi, nilai aktual untuk $string
selalu tetap apa pun itu ketika Anda terakhir kali menetapkannya. Jadi mari kita kembali ke hal pertama.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
KELUARAN
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
Saya percaya ini adalah cara yang jauh lebih waras untuk mengadaptasi sintaksis shell dengan preferensi indentasi Anda. Apa yang saya lakukan di atas adalah menugaskan setiap string individu ke parameter posisi - yang masing-masing dapat direferensikan dengan angka seperti $1
atau ${33}
- dan kemudian menetapkan nilai gabungan mereka untuk $var
menggunakan parameter shell khusus $*
.
Pendekatan ini tidak kebal terhadap $IFS
hal itu. Namun, saya menganggap hubungannya dengan $IFS
manfaat tambahan dalam hal ini. Mempertimbangkan:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
KELUARAN
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
Seperti yang Anda lihat, $*
gabungkan masing-masing arg "$@"
pada byte pertama di $IFS
. Jadi menyimpan nilainya saat $IFS
ditugaskan secara berbeda akan mendapat pembatas bidang yang berbeda untuk setiap nilai yang disimpan. Apa yang Anda lihat di atas adalah nilai literal untuk setiap variabel. Jika Anda tidak menginginkan pembatas sama sekali, Anda akan melakukannya:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
KELUARAN
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67