Cara yang mungkin paling mudah dan paling aman di BASH 3 dan di atas adalah:
var="string to split"
read -ra arr <<<"$var"
(di mana arr
array yang mengambil bagian-bagian yang terpisah dari string) atau, jika mungkin ada baris baru di input dan Anda ingin lebih dari sekadar baris pertama:
var="string to split"
read -ra arr -d '' <<<"$var"
(harap perhatikan spasi di -d ''
, tidak dapat ditinggalkan), tetapi ini mungkin memberi Anda baris baru yang tidak terduga <<<"$var"
(karena ini secara implisit menambahkan LF pada akhirnya).
Contoh:
touch NOPE
var="* a *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done
Output yang diharapkan
[*]
[a]
[*]
karena solusi ini (berbeda dengan semua solusi sebelumnya di sini) tidak rentan terhadap globbing shell yang tak terduga dan sering tidak terkendali.
Juga ini memberi Anda kekuatan penuh IFS seperti yang Anda inginkan:
Contoh:
IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done
Menghasilkan sesuatu seperti:
[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]
Seperti yang Anda lihat, ruang juga dapat dipertahankan dengan cara ini:
IFS=: read -ra arr <<<' split : this '
for a in "${arr[@]}"; do echo "[$a]"; done
output
[ split ]
[ this ]
Harap perhatikan bahwa penanganan IFS
dalam BASH adalah subjek tersendiri, jadi lakukan pengujian Anda, beberapa topik menarik tentang ini:
unset IFS
: Mengabaikan menjalankan SPC, TAB, NL dan on line dimulai dan berakhir
IFS=''
: Tidak ada pemisahan bidang, hanya membaca semuanya
IFS=' '
: Jalankan SPC (dan hanya SPC)
Beberapa contoh terakhir
var=$'\n\nthis is\n\n\na test\n\n'
IFS=$'\n' read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done
output
1 [this is]
2 [a test]
sementara
unset IFS
var=$'\n\nthis is\n\n\na test\n\n'
read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done
output
1 [this]
2 [is]
3 [a]
4 [test]
BTW:
Jika Anda tidak $'ANSI-ESCAPED-STRING'
terbiasa dengan itu, itu adalah penghemat waktu.
Jika Anda tidak memasukkan -r
(seperti dalam read -a arr <<<"$var"
) maka baca apakah backslash lolos. Ini dibiarkan sebagai latihan untuk pembaca.
Untuk pertanyaan kedua:
Untuk menguji sesuatu dalam string saya biasanya tetap berpegang pada case
, karena ini dapat memeriksa beberapa kasus sekaligus (catatan: case hanya mengeksekusi pertandingan pertama, jika Anda perlu fallthrough menggunakan case
pernyataan multiplce ), dan kebutuhan ini cukup sering terjadi case (pun dimaksudkan):
case "$var" in
'') empty_var;; # variable is empty
*' '*) have_space "$var";; # have SPC
*[[:space:]]*) have_whitespace "$var";; # have whitespaces like TAB
*[^-+.,A-Za-z0-9]*) have_nonalnum "$var";; # non-alphanum-chars found
*[-+.,]*) have_punctuation "$var";; # some punctuation chars found
*) default_case "$var";; # if all above does not match
esac
Jadi, Anda dapat mengatur nilai balik untuk memeriksa SPC seperti ini:
case "$var" in (*' '*) true;; (*) false;; esac
Mengapa case
? Karena biasanya sedikit lebih mudah dibaca daripada urutan regex, dan berkat karakter meta Shell ia menangani 99% dari semua kebutuhan dengan sangat baik.