Di sini masalahnya adalah Anda mengelilingi variabel dengan tanda kutip ganda (""). Hapus itu dan semuanya akan berfungsi dengan baik.
VAR="This displays with \
extra spaces."
echo ${VAR}
Keluaran
This displays with extra spaces.
Di sini masalahnya adalah bahwa mengutip dua variabel mempertahankan semua karakter spasi putih. Ini dapat digunakan jika Anda membutuhkannya secara eksplisit.
Sebagai contoh,
$ echo "Hello World ........ ... ...."
akan dicetak
Hello World ........ ... ....
Dan pada menghapus kutipan, ini berbeda
$ echo Hello World ........ ... ....
Hello World ........ ... ....
Di sini Bash menghapus spasi tambahan dalam teks karena dalam kasus pertama seluruh teks diambil sebagai argumen "tunggal" dan dengan demikian mempertahankan ruang ekstra. Tetapi dalam kasus kedua echo
perintah menerima teks sebagai 5 argumen.
Mengutip variabel juga akan membantu saat menyampaikan argumen ke perintah.
Pada perintah di bawah ini, echo
hanya mendapat satu argumen sebagai"Hello World"
$ variable="Hello World"
$ echo "$variable"
Tetapi dalam kasus skenario di bawah ini echo
mendapat dua argumen sebagai Hello
danWorld
$ variable="Hello World"
$ echo $variable
$IFS
adalah alat yang kuat dan universal - tetapi kode yang ditulis dengan cara ini tidak pernah dapat menghasilkan hasil yang dapat diandalkan dalam bentuk apa pun.*
?
[]
).Solusi yang diberikan oleh esuoxu dan Mickaël Bucas adalah cara umum dan lebih portabel untuk melakukan ini.
Berikut adalah beberapa
bash
solusi (beberapa di antaranya juga dapat bekerja di shell lain, sepertizsh
). Pertama dengan+=
append operator (yang bekerja dengan cara yang sedikit berbeda untuk masing-masing variabel integer, variabel reguler, dan array).Jika Anda ingin baris baru (atau spasi / lolos lainnya) dalam teks, gunakan
$''
kutipan:Selanjutnya, gunakan
printf -v
untuk menetapkan nilai yang diformat ke variabelKuncinya di sini adalah bahwa ada lebih banyak argumen daripada penentu format, jadi tidak seperti kebanyakan
printf
fungsi, yang bash menggunakan kembali format string sampai habis. Anda dapat menempatkan\n
dalam string format, atau menggunakan $ '', (atau keduanya) untuk menangani spasi putih.Selanjutnya, menggunakan array:
Anda juga dapat menggunakan
+=
untuk membangun teks baris demi baris (perhatikan()
):Namun di sini, Anda harus ingat untuk "meratakan" array jika Anda ingin seluruh konten teks sekaligus
(array integer yang diindeks secara implisit diurutkan, tidak seperti array asosiatif) Ini memberi Anda sedikit lebih banyak fleksibilitas karena Anda dapat memanipulasi garis dan bahkan mengiris dan memotong jika diperlukan.
Akhirnya, menggunakan
read
ataureadarray
dan "dokumen-sini":Bentuk di sini dokumen
<<-
berarti semua tab keras utama dihapus dari input, jadi Anda harus menggunakan tab untuk membuat indentasi teks Anda. Mengutip sekitar"EOT"
mencegah fitur ekspansi shell, sehingga input digunakan kata demi kata. Denganread
itu menggunakan input dibatasi NUL byte, sehingga akan membaca teks yang dibatasi baris baru dalam sekali jalan. Denganreadarray
(aliasmapfile
, tersedia sejak bash-4.0) ia membaca ke dalam sebuah array, dan-t
menghapus baris baru di setiap baris.sumber
read
pilihan denganhere document
sangat bagus! Berguna untuk menanamkan skrip python dan mengeksekusi denganpython -c
. Saya pernah melakukannyascript=$(cat <here document>)
sebelumnya, tetapiread -r -d '' script <here document>
jauh lebih baik.Ada sintaks heredoc khusus yang menghapus tab di awal semua baris: "<< -" (perhatikan tanda hubung ditambahkan)
http://tldp.org/LDP/abs/html/here-docs.html
Contoh 19-4. Pesan multi-line, dengan tab ditekan
Anda bisa menggunakannya seperti ini:
Hasil:
Ini hanya berfungsi dengan tab, bukan spasi.
sumber
\t
bekerja sangat baik jika Anda membutuhkan tab. Cukup gunakanecho -e "$v"
daripadaecho "$v"
untuk mengaktifkan karakter backslashBiarkan cangkang memakan biji-bijian yang tidak diinginkan dan spasi berikut:
Jadi itu mungkin ... tapi yakin itu masalah selera untuk suka atau tidak suka solusi ini ...
sumber
Mungkin Anda bisa mencoba ini.
sumber
Begini saran saya, Anda harus melakukannya, dan saya akan menjelaskan alasannya, tetapi pertama-tama saya ingin berbicara tentang sesuatu yang lain ...
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.
KELUARAN
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.
Sama
$string
- lingkungan berbeda.KELUARAN
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 sebabnyaecho
ekspansi yang berisi urutan ruang mana pun ketika$IFS
berisi ruang akan mengevaluasi hanya ruang tunggal - karenaecho
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
.KELUARAN
Terlihat oke, bukan? Baiklah, mari kita ubah lingkungan lagi.
KELUARAN
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.KELUARAN
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:KELUARAN
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:KELUARAN
sumber
Anda mungkin ingin mencoba:
atau
dan juga Anda dapat memeriksa ini keluar.
sumber
Gunakan Ekspansi Substitusi Bash
Jika Anda menggunakan Bash, Anda dapat menggunakan ekspansi substitusi . Sebagai contoh:
sumber
Ini adalah varian untuk menyetel variabel path-like:
Menggunakan
set
overwrites$@
, yang dapat disimpan dan digunakan kemudian sebagai berikut:The
LD_LIBRARY_PATH=$(sed 's/ :/:/g' <<< $LD_LIBRARY_PATH)
eliminasi baris spasi sebelum titik dua serta mungkin spasi trailing. Jika hanya menghilangkan spasi tambahan, gunakanLD_LIBRARY_PATH=${LD_LIBRARY_PATH%% }
saja.Seluruh pendekatan ini merupakan varian dari jawaban mikeserv yang luar biasa.
sumber
Jangan takut dengan karakter spasi putih. Hapus saja sebelum Anda mencetak teks multiline Anda.
Keluaran:
Tidak perlu menggunakan
<<-
heredoc dan hancurkan indentasi 4-ruang Anda dengan karakter tab.sumber