Saya punya string:
one_two_three_four_five
Saya perlu menyimpan A
nilai variabel two
dan B
nilai variabel four
dari string di atas
Gunakan cut
dengan _
sebagai pembatas bidang dan dapatkan bidang yang diinginkan:
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
Anda juga bisa menggunakan echo
dan mem-pipe bukannya string Here:
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
Contoh:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
Apakah Anda tahu apa yang terjadi di sini?echo "${s##*_}"
Hanya menggunakan konstruksi sh POSIX, Anda bisa menggunakan konstruksi substitusi parameter untuk mengurai satu pembatas pada satu waktu. Perhatikan bahwa kode ini mengasumsikan bahwa ada jumlah bidang yang diperlukan, jika tidak, bidang terakhir diulang.
Atau, Anda dapat menggunakan substitusi parameter yang tidak dikutip dengan ekspansi wildcard dinonaktifkan dan
IFS
diatur ke karakter pembatas (ini hanya bekerja jika pembatas adalah karakter non-spasi tunggal atau jika urutan spasi apa pun adalah pembatas).Ini mengacaukan parameter posisi. Jika Anda melakukan ini dalam suatu fungsi, hanya parameter posisi fungsi yang terpengaruh.
Namun pendekatan lain adalah dengan menggunakan
read
builtin.sumber
unset IFS
tidak kembaliIFS
ke default. Jika setelah itu seseorangOldIFS="$IFS"
akan memiliki nilai nol di dalam OldIFS. Juga, diasumsikan bahwa nilai IFS sebelumnya adalah default, yang sangat mungkin (dan berguna) untuk tidak. Satu-satunya solusi yang benar adalah menyimpanold="$IFS"
dan mengembalikan dengan IFS = "$ old". Atau ... gunakan sub-shell(...)
. Atau, lebih baik lagi, baca jawaban saya.unset IFS
tidak mengembalikanIFS
ke nilai default, tetapi mengembalikan pemisahan bidang ke efek default. Ya, ini adalah batasan, tetapi biasanya yang dapat diterima dalam praktik. Masalah dengan subkulit adalah kita perlu mengambil data darinya. Saya memang menunjukkan solusi yang tidak mengubah keadaan pada akhirnya, denganread
. (Ini bekerja di shell POSIX, tetapi IIRC tidak di shell Bourne karena ia akan menjalankanread
dalam subkulit karena dokumen di sini.) Menggunakan<<<
seperti pada jawaban Anda adalah varian yang hanya bekerja di ksh / bash / zsh.user/my_folder/[this_is_my_file]*
? Apa yang saya dapatkan ketika saya mengikuti langkah-langkah ini adalah[this_is_my_file]*
/
.Ingin melihat
awk
jawaban, jadi ini satu:sumber
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
Cara paling sederhana (untuk kerang dengan <<<) adalah:
Menggunakan variabel temporal
$a
alih-alih$_
karena satu shell mengeluh.Dalam skrip lengkap:
Tidak ada perubahan IFS, bukan masalah dengan
set -f
(Perluasan pathname) Tidak ada perubahan pada parameter posisi ("$ @").Untuk solusi portabel untuk semua shell (ya, semua POSIX termasuk) tanpa mengubah IFS atau
set -f
, gunakan (setara dengan sedikit lebih kompleks) heredoc:Memahami bahwa solusi ini (baik di sini-doc dan penggunaan
<<<
akan menghapus semua baris baru.Dan bahwa ini dirancang untuk konten variabel "satu liner."
Solusi untuk multi-liner dimungkinkan tetapi membutuhkan konstruksi yang lebih kompleks.
Solusi yang sangat sederhana dimungkinkan di versi bash 4.4
Tidak ada padanan untuk shell POSIX, karena banyak shell POSIX tidak memiliki array.
Untuk cangkang yang memiliki larik mungkin sesederhana:
(diuji bekerja di attsh, lksh, mksh, ksh, dan bash)
Tetapi dengan banyak pipa tambahan untuk menjaga dan mengatur ulang variabel dan opsi:
Di zsh, array dimulai pada 1, dan tidak memisah string secara default.
Jadi beberapa perubahan perlu dilakukan untuk mendapatkan ini berfungsi di zsh.
sumber
read
sederhana selama OP tidak ingin mengekstraksi elemen ke-76 dan ke-127 dari string panjang ...readarray
bisa lebih mudah digunakan untuk situasi itu.Dengan
zsh
Anda dapat membagi string (on_
) menjadi array:dan kemudian mengakses setiap elemen melalui indeks array:
Perlu diingat bahwa dalam indeks array
zsh
(tidak sepertiksh
/bash
) mulai dari 1 .sumber
set -f
peringatan ke solusi pertama. ... tanda bintang*
mungkin?set -f
? Saya tidak menggunakanread
/IFS
. Coba solusi saya dengan string seperti*_*_*
atau apa pun ...Apakah solusi python diizinkan?
sumber
Contoh awk lainnya; lebih mudah dimengerti.
Dapat digunakan dengan variabel juga.
Misalkan:
this_str = "one_two_three_four_five"
Maka yang berikut berfungsi:
A = `echo $ {this_str} | awk -F_ '{print $ 1}' `
B =` echo $ {this_str} | awk -F_ '{print $ 2}' `
C =` echo $ {this_str} | awk -F_ '{print $ 3}' `
... dan seterusnya ...
sumber