Saya memiliki string yang berisi banyak kata dengan setidaknya satu spasi di antara keduanya. Bagaimana saya bisa membagi string menjadi kata-kata individual sehingga saya bisa memutarnya?
String dilewatkan sebagai argumen. Misalnya ${2} == "cat cat file"
. Bagaimana saya bisa memutarnya?
Juga, bagaimana saya bisa memeriksa apakah string berisi spasi?
Jawaban:
Apakah Anda mencoba meneruskan variabel string ke
for
loop? Bash, misalnya, akan terpecah pada spasi putih secara otomatis.sumber
A=${A}${word})
.touch NOPE; var='* a *'; for a in $var; do echo "[$a]"; done
output[NOPE] [a] [NOPE]
bukan yang diharapkan[*] [a] [*]
(LF digantikan oleh SPC untuk dibaca).Saya suka konversi ke array, untuk dapat mengakses elemen individual:
sekarang Anda dapat mengakses setiap elemen secara langsung (dimulai dengan 0):
atau konversi kembali ke string untuk mengulang:
Tentu saja perulangan melalui string langsung dijawab sebelumnya, tetapi jawaban itu memiliki kelemahan untuk tidak melacak elemen individu untuk digunakan nanti:
Lihat juga Referensi Bash Array .
sumber
touch NOPE; var='* a *'; arr=($var); set | grep ^arr=
outputarr=([0]="NOPE" [1]="a" [2]="NOPE")
bukannya yang diharapkanarr=([0]="*" [1]="a" [2]="*")
Cukup gunakan shell "set" built-in. Sebagai contoh,
Setelah itu, kata-kata individual dalam $ text akan menjadi $ 1, $ 2, $ 3, dll. Untuk ketahanan, biasanya satu
untuk menangani case di mana $ text kosong atau mulai dengan tanda hubung. Sebagai contoh:
Ini mencetak
sumber
awk
tetapiset
jauh lebih mudah. Saya sekarang seorangset
fanboy. Terima kasih @ Idelic!touch NOPE; var='* a *'; set -- $var; for a; do echo "[$a]"; done
output[NOPE] [a] [NOPE]
bukannya yang diharapkan[*] [a] [*]
. Hanya gunakan itu jika Anda yakin 101% bahwa tidak ada metakarakter SHELL dalam string yang terpecah!set -f
sebelumset -- $var
danset +f
sesudahnya untuk menonaktifkan globbing.set -f
solusi Anda juga aman. Tetapiset +f
ini adalah default dari masing-masing shell, jadi ini adalah detail penting, yang harus dicatat, karena yang lain mungkin tidak menyadarinya (seperti saya juga).Cara yang mungkin paling mudah dan paling aman di BASH 3 dan di atas adalah:
(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:(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:
Output yang diharapkan
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:
Menghasilkan sesuatu seperti:
Seperti yang Anda lihat, ruang juga dapat dipertahankan dengan cara ini:
output
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 berakhirIFS=''
: Tidak ada pemisahan bidang, hanya membaca semuanyaIFS=' '
: Jalankan SPC (dan hanya SPC)Beberapa contoh terakhir
output
sementara
output
BTW:
Jika Anda tidak
$'ANSI-ESCAPED-STRING'
terbiasa dengan itu, itu adalah penghemat waktu.Jika Anda tidak memasukkan
-r
(seperti dalamread -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 menggunakancase
pernyataan multiplce ), dan kebutuhan ini cukup sering terjadi case (pun dimaksudkan):Jadi, Anda dapat mengatur nilai balik untuk memeriksa SPC seperti ini:
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.sumber
set -f
atauset -o noglob
untuk beralih globbing, sehingga karakter meta shell tidak lagi membahayakan dalam konteks ini. Tapi saya bukan benar-benar teman itu, karena ini meninggalkan banyak kekuatan shell / sangat rentan untuk beralih bolak-balik pengaturan ini.;&
mencapainya. Tidak yakin versi bash mana yang muncul. Saya pengguna 4.3;&
adalah fallthrough yang dipaksakan tanpa pemeriksaan pola seperti di C. Dan ada juga;;&
yang terus melakukan pemeriksaan pola lebih lanjut. Begitu;;
jugaif ..; then ..; else if ..
dan;;&
itu sepertiif ..; then ..; fi; if ..
, di mana;&
sepertim=false; if ..; then ..; m=:; fi; if $m || ..; then ..
- seseorang tidak pernah berhenti belajar (dari orang lain););;&
sebelum Anda berkomentar: D Terima kasih, dan mungkin cangkangnya bersamamu;)Untuk memeriksa spasi, gunakan grep:
sumber
echo "X" |
biasanya dapat digantikan oleh<<<"X"
, seperti ini:grep -s " " <<<"This contains SPC"
. Anda dapat melihat perbedaannya jika Anda melakukan sesuatu yangecho X | read var
berbeda denganread var <<< X
. Hanya yang terakhir mengimpor variabelvar
ke shell saat ini, sementara untuk mengaksesnya di varian pertama Anda harus mengelompokkan seperti ini:echo X | { read var; handle "$var"; }
(A) Untuk membagi kalimat menjadi kata-katanya (dipisahkan spasi) Anda cukup menggunakan IFS default dengan menggunakan
Contoh menjalankan cuplikan berikut
akan menampilkan
Seperti yang Anda lihat, Anda dapat menggunakan tanda kutip tunggal atau ganda juga tanpa masalah.
Catatan:
- ini pada dasarnya sama dengan jawaban mob , tetapi dengan cara ini Anda menyimpan array untuk keperluan lebih lanjut. Jika Anda hanya memerlukan satu loop, Anda dapat menggunakan jawabannya, yang merupakan satu baris lebih pendek :)
- silakan lihat pertanyaan ini untuk metode alternatif untuk membagi string berdasarkan pembatas.
(B) Untuk memeriksa karakter dalam string, Anda juga dapat menggunakan pencocokan ekspresi reguler.
Contoh untuk memeriksa keberadaan karakter spasi yang dapat Anda gunakan:
sumber
Untuk memeriksa ruang hanya dengan bash:
sumber
Ini menghasilkan setiap kata, Anda dapat memproses daftar itu sesuai keinginan sesudahnya.
sumber