it-swarm-id.com

Bagaimana cara memisahkan string pada pembatas di Bash?

Saya memiliki string ini disimpan dalam variabel:

IN="[email protected];[email protected]"

Sekarang saya ingin membagi string dengan pemisah ; sehingga saya punya:

ADDR1="[email protected]"
ADDR2="[email protected]"

Saya tidak perlu variabel ADDR1 dan ADDR2. Jika mereka adalah elemen dari array itu bahkan lebih baik.


Setelah saran dari jawaban di bawah, saya berakhir dengan yang berikut yang saya cari:

#!/usr/bin/env bash

IN="[email protected];[email protected]"

mails=$(echo $IN | tr ";" "\n")

for addr in $mails
do
    echo "> [$addr]"
done

Keluaran:

> [[email protected]]
> [[email protected]]

Ada solusi yang melibatkan pengaturan Internal_field_separator (IFS) ke ;. Saya tidak yakin apa yang terjadi dengan jawaban itu, bagaimana Anda mengatur ulang IFS kembali ke default?

RE: IFS solusi, saya mencoba ini dan berhasil, saya menjaga IFS lama dan mengembalikannya

IN="[email protected];[email protected]"

OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
    echo "> [$x]"
done

IFS=$OIFS

BTW, ketika saya mencoba

mails2=($IN)

Saya hanya mendapatkan string pertama saat mencetaknya dalam lingkaran, tanpa tanda kurung di $IN berfungsi.

1733
stefanB

Anda bisa mengatur variabel bidang pemisah internal (IFS) variabel, dan kemudian membiarkannya mengurai menjadi array. Ketika ini terjadi dalam suatu perintah, maka penugasan ke IFS hanya terjadi pada lingkungan perintah tunggal itu (ke read). Ini kemudian mem-parsing input sesuai dengan nilai variabel IFS ke dalam array, yang kemudian dapat kita iterate.

IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
    # process "$i"
done

Ini akan mengurai satu baris item yang dipisahkan oleh ;, mendorongnya ke dalam array. Hal-hal untuk memproses seluruh $IN, setiap kali satu baris input dipisahkan oleh ;:

 while IFS=';' read -ra ADDR; do
      for i in "${ADDR[@]}"; do
          # process "$i"
      done
 done <<< "$IN"
1067

Diambil dariBash Shell script split array:

IN="[email protected];[email protected]"
arrIN=(${IN//;/ })

Penjelasan:

Konstruksi ini menggantikan semua kemunculan ';' (// awal berarti ganti global) dalam string IN dengan ' ' (satu spasi), lalu mengartikan string yang dibatasi ruang sebagai array (itulah yang dilakukan oleh kurung sekitarnya).

Sintaks yang digunakan di dalam kurung kurawal untuk mengganti setiap karakter ';' dengan karakter ' ' disebut Parameter Expansion .

Ada beberapa gotcha yang umum:

  1. Jika string asli memiliki spasi, Anda harus menggunakan IFS :
    • IFS=':'; arrIN=($IN); unset IFS;
  2. Jika string asli memiliki spasi dan pembatas adalah baris baru, Anda dapat mengatur IFS dengan:
    • IFS=$'\n'; arrIN=($IN); unset IFS;
843
palindrom

Jika Anda tidak keberatan memprosesnya segera, saya suka melakukan ini:

for i in $(echo $IN | tr ";" "\n")
do
  # process
done

Anda bisa menggunakan loop semacam ini untuk menginisialisasi array, tetapi mungkin ada cara yang lebih mudah untuk melakukannya. Semoga ini bisa membantu.

220
Chris Lutz

Jawaban yang kompatibel

Untuk pertanyaan SO ini, sudah ada banyak cara berbeda untuk melakukan ini di bash . Tetapi bash memiliki banyak fitur khusus, yang disebut bashism yang bekerja dengan baik, tetapi itu tidak akan berfungsi di Shell lainnya.

Secara khusus, array, array asosiatif, dan substitusi pola adalah murni bashisms dan mungkin tidak berfungsi di bawah shelllainnya _.

Pada Debian GNU/Linuxsaya, ada standar Shell disebut dash , tapi saya tahu banyak orang yang suka menggunakan ksh .

Akhirnya, dalam situasi yang sangat kecil, ada alat khusus yang disebut busybox dengan penerjemah Shellnya sendiri ( ash ).

String yang diminta

Sampel string dalam SO pertanyaan adalah:

IN="[email protected];[email protected]"

Karena ini bisa berguna dengan whitespaces dan sebagai whitespaces dapat mengubah hasil dari rutin, saya lebih suka menggunakan string sampel ini:

 IN="[email protected];[email protected];Full Name <[email protected]>"

Pisahkan string berdasarkan pembatas di bash (versi> = 4.2)

Di bawah pure bash, kita dapat menggunakan array dan IFS:

var="[email protected];[email protected];Full Name <[email protected]>"
oIFS="$IFS"
IFS=";"
declare -a fields=($var)
IFS="$oIFS"
unset oIFS
IFS=\; read -a fields <<<"$IN"

Menggunakan sintaks ini di bawah bash baru-baru ini jangan mengubah $IFS untuk sesi saat ini, tetapi hanya untuk perintah saat ini:

set | grep ^IFS=
IFS=$' \t\n'

Sekarang string var dipecah dan disimpan ke dalam array (dinamai fields):

set | grep ^fields=\\\|^var=
fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")
var='[email protected];[email protected];Full Name <[email protected]>'

Kami dapat meminta konten variabel dengan declare -p:

declare -p IN fields
declare -- IN="[email protected];[email protected];Full Name <[email protected]>"
declare -a fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")

read adalah tercepat cara untuk melakukan pemisahan, karena tidak ada garpu dan tidak ada sumber daya eksternal yang disebut.

Dari sana, Anda bisa menggunakan sintaks yang sudah Anda ketahui untuk memproses setiap bidang:

for x in "${fields[@]}";do
    echo "> [$x]"
    done
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]

atau letakkan setiap bidang setelah pemrosesan (saya suka pendekatan ini {bergeser):

while [ "$fields" ] ;do
    echo "> [$fields]"
    fields=("${fields[@]:1}")
    done
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]

atau bahkan untuk cetakan sederhana (sintaksis lebih pendek):

printf "> [%s]\n" "${fields[@]}"
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]

Pembaruan: terkini bash > = 4.4

Anda bisa bermain dengan mapfile:

mapfile -td \; fields < <(printf "%s\0" "$IN")

Sintaks ini mempertahankan karakter khusus, baris baru, dan bidang kosong!

Jika Anda tidak peduli dengan bidang kosong, Anda dapat:

mapfile -td \; fields <<<"$IN"
fields=("${fields[@]%$'\n'}")   # drop '\n' added by '<<<'

Tapi Anda bisa menggunakan bidang melalui fungsi:

myPubliMail() {
    printf "Seq: %6d: Sending mail to '%s'..." $1 "$2"
    # mail -s "This is not a spam..." "$2" </path/to/body
    printf "\e[3D, done.\n"
}

mapfile < <(printf "%s\0" "$IN") -td \; -c 1 -C myPubliMail

(Nota: \0 di akhir string format tidak berguna sementara Anda tidak peduli dengan bidang kosong di akhir string)

mapfile < <(echo -n "$IN") -td \; -c 1 -C myPubliMail

Akan membuat sesuatu seperti:

Seq:      0: Sending mail to '[email protected]', done.
Seq:      1: Sending mail to '[email protected]', done.
Seq:      2: Sending mail to 'Full Name <[email protected]>', done.

Atau Lepaskan baris baru yang ditambahkan oleh <<< sintaks bash dalam fungsi:

myPubliMail() {
    local seq=$1 dest="${2%$'\n'}"
    printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest"
    # mail -s "This is not a spam..." "$dest" </path/to/body
    printf "\e[3D, done.\n"
}

mapfile <<<"$IN" -td \; -c 1 -C myPubliMail

Akan menghasilkan keluaran yang sama:

Seq:      0: Sending mail to '[email protected]', done.
Seq:      1: Sending mail to '[email protected]', done.
Seq:      2: Sending mail to 'Full Name <[email protected]>', done.

Membagi string berdasarkan pembatas di Shell

Tetapi jika Anda ingin menulis sesuatu yang dapat digunakan di bawah banyak shell, Anda harus tidak menggunakan bashisms.

Ada sintaks, yang digunakan dalam banyak shell, untuk memisahkan string di pertama atau terakhir terjadinya substring:

${var#*SubStr}  # will drop begin of string up to first occur of `SubStr`
${var##*SubStr} # will drop begin of string up to last occur of `SubStr`
${var%SubStr*}  # will drop part of string from last occur of `SubStr` to the end
${var%%SubStr*} # will drop part of string from first occur of `SubStr` to the end

(Hilangnya ini adalah alasan utama dari publikasi jawaban saya;)

Seperti yang ditunjukkan oleh Score_Under :

# dan % menghapus string pencocokan sesingkat mungkin, dan

## dan %% hapus yang terpanjang.

di mana # dan ## berarti dari kiri (mulai) dari string, dan

% dan %% meand dari kanan (akhir) dari string.

Skrip sampel kecil ini bekerja dengan baik di bawah bash , dash , ksh , busybox dan juga diuji di bawah bash Mac-OS:

var="[email protected];[email protected];Full Name <[email protected]>"
while [ "$var" ] ;do
    iter=${var%%;*}
    echo "> [$iter]"
    [ "$var" = "$iter" ] && \
        var='' || \
        var="${var#*;}"
  done
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]

Selamat bersenang-senang!

159
F. Hauri

Saya telah melihat beberapa jawaban yang merujuk pada perintah cut, tetapi semuanya sudah dihapus. Agak aneh bahwa tidak ada yang menjelaskan hal itu, karena saya pikir itu salah satu perintah yang lebih berguna untuk melakukan hal semacam ini, terutama untuk mem-parsing file log yang dibatasi.

Dalam kasus pemisahan contoh spesifik ini menjadi array bash script, tr mungkin lebih efisien, tetapi cut dapat digunakan, dan lebih efektif jika Anda ingin menarik bidang tertentu dari tengah.

Contoh:

$ echo "[email protected];[email protected]" | cut -d ";" -f 1
[email protected]
$ echo "[email protected];[email protected]" | cut -d ";" -f 2
[email protected]

Anda jelas dapat memasukkannya ke dalam satu lingkaran, dan lakukan iterasi pada parameter -f untuk menarik masing-masing bidang secara independen.

Ini menjadi lebih berguna ketika Anda memiliki file log terbatas dengan baris seperti ini:

2015-04-27|12345|some action|an attribute|meta data

cut sangat berguna untuk dapat cat file ini dan memilih bidang tertentu untuk diproses lebih lanjut.

124
DougW

Ini bekerja untuk saya:

string="1;2"
echo $string | cut -d';' -f1 # output is 1
echo $string | cut -d';' -f2 # output is 2
91
Steven Lizarazo

Bagaimana dengan pendekatan ini:

IN="[email protected];[email protected]" 
set -- "$IN" 
IFS=";"; declare -a Array=($*) 
echo "${Array[@]}" 
echo "${Array[0]}" 
echo "${Array[1]}" 

Sumber

83
errator
62
lothar

Ini juga berfungsi:

IN="[email protected];[email protected]"
echo ADD1=`echo $IN | cut -d \; -f 1`
echo ADD2=`echo $IN | cut -d \; -f 2`

Hati-hati, solusi ini tidak selalu benar. Jika Anda melewati "[email protected]" saja, itu akan menetapkannya untuk ADD1 dan ADD2.

61
Ashok

Saya pikir AWK adalah perintah terbaik dan efisien untuk menyelesaikan masalah Anda. AWK termasuk dalam Bash secara default di hampir setiap distribusi Linux.

echo "[email protected];[email protected]" | awk -F';' '{print $1,$2}'

akan memberi

[email protected] [email protected]

Tentu saja Anda dapat menyimpan setiap alamat email dengan mendefinisikan kembali bidang cetak awk.

38
Tony

Pandangan berbeda tentang jawaban Darron , ini adalah bagaimana saya melakukannya:

IN="[email protected];[email protected]"
read ADDR1 ADDR2 <<<$(IFS=";"; echo $IN)
30
nickjb

Di Bash, cara anti peluru, itu akan berfungsi bahkan jika variabel Anda berisi baris baru:

IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")

Melihat:

$ in=$'one;two three;*;there is\na newline\nin this field'
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is
a newline
in this field")'

Trik agar ini berfungsi adalah dengan menggunakan opsi -d dari read (pembatas) dengan pembatas kosong, sehingga read dipaksa untuk membaca semua yang diumpankan. Dan kami memberi read dengan isi variabel in, tanpa baris tambahan berkat printf. Perhatikan bahwa kami juga meletakkan pembatas di printf untuk memastikan bahwa string yang dilewati ke read memiliki pembatas trailing. Tanpanya, read akan memangkas potensi jejak bidang kosong:

$ in='one;two;three;'    # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'

bidang kosong yang tertinggal dipertahankan.


Perbarui untuk Bash≥4.4

Sejak Bash 4.4, builtin mapfile (alias readarray) mendukung opsi -d untuk menentukan pembatas. Karenanya cara kanonik lainnya adalah:

mapfile -d ';' -t array < <(printf '%s;' "$in")
26
gniourf_gniourf

Bagaimana dengan liner satu ini, jika Anda tidak menggunakan array:

IFS=';' read ADDR1 ADDR2 <<<$IN
20
Darron

Ini adalah 3-liner bersih:

in="[email protected];[email protected];[email protected];[email protected]"
IFS=';' list=($in)
for item in "${list[@]}"; do echo $item; done

di mana kata pembatas IFS berdasarkan pada pemisah dan () digunakan untuk membuat array . Kemudian [@] digunakan untuk mengembalikan setiap item sebagai kata yang terpisah.

Jika Anda memiliki kode setelah itu, Anda juga harus mengembalikan $IFS, mis. unset IFS.

19
kenorb

Tanpa mengatur IFS

Jika Anda hanya memiliki satu titik dua, Anda dapat melakukannya:

a="foo:bar"
b=${a%:*}
c=${a##*:}

kamu akan mendapatkan:

b = foo
c = bar
16
Emilien Brigand

Fungsi Bash/zsh berikut membagi argumen pertamanya pada pembatas yang diberikan oleh argumen kedua:

split() {
    local string="$1"
    local delimiter="$2"
    if [ -n "$string" ]; then
        local part
        while read -d "$delimiter" part; do
            echo $part
        done <<< "$string"
        echo $part
    fi
}

Misalnya, perintahnya

$ split 'a;b;c' ';'

hasil panen

a
b
c

Output ini dapat, misalnya, disalurkan ke perintah lain. Contoh:

$ split 'a;b;c' ';' | cat -n
1   a
2   b
3   c

Dibandingkan dengan solusi lain yang diberikan, yang ini memiliki keunggulan sebagai berikut:

  • IFS tidak diganti: Karena pelingkupan dinamis dari variabel lokal, menimpa IFS pada suatu loop menyebabkan nilai baru bocor ke panggilan fungsi yang dilakukan dari dalam loop.

  • Array tidak digunakan: Membaca string ke dalam array menggunakan read membutuhkan flag -a di Bash dan -A di zsh.

Jika diinginkan, fungsi dapat dimasukkan ke dalam skrip sebagai berikut:

#!/usr/bin/env bash

split() {
    # ...
}

split "[email protected]"
8
Halle Knast

Ada cara sederhana dan cerdas seperti ini:

echo "add:sfff" | xargs -d: -i  echo {}

Tetapi Anda harus menggunakan gnu xargs, BSD xargs tidak dapat mendukung -d delim. Jika Anda menggunakan Apple mac seperti saya. Anda dapat menginstal gnu xargs:

brew install findutils

kemudian

echo "add:sfff" | gxargs -d: -i  echo {}
7
Victor Choy

anda dapat menerapkan awk ke banyak situasi

echo "[email protected];[email protected]"|awk -F';' '{printf "%s\n%s\n", $1, $2}'

anda juga bisa menggunakan ini

echo "[email protected];[email protected]"|awk -F';' '{print $1,$2}' OFS="\n"
6
shuaihanhungry

Ini adalah cara paling sederhana untuk melakukannya.

spo='one;two;three'
OIFS=$IFS
IFS=';'
spo_array=($spo)
IFS=$OIFS
echo ${spo_array[*]}
5
Arcabard

Ada beberapa jawaban keren di sini (errator esp.), Tetapi untuk sesuatu yang analog untuk dipecah dalam bahasa lain - yang saya maksud dengan pertanyaan aslinya - saya memutuskan untuk ini:

IN="[email protected];[email protected]"
declare -a a="(${IN/;/ })";

Sekarang ${a[0]}, ${a[1]}, dll, seperti yang Anda harapkan. Gunakan ${#a[*]} untuk sejumlah istilah. Atau untuk beralih, tentu saja:

for i in ${a[*]}; do echo $i; done

CATATAN PENTING:

Ini bekerja dalam kasus di mana tidak ada ruang untuk dikhawatirkan, yang memecahkan masalah saya, tetapi mungkin tidak menyelesaikan masalah Anda. Pergilah dengan solusi $IFS dalam hal itu.

4
eukras
IN="[email protected];[email protected]"
IFS=';'
read -a IN_arr <<< "${IN}"
for entry in "${IN_arr[@]}"
do
    echo $entry
done

Keluaran

[email protected]
[email protected]

Sistem: Ubuntu 12.04.1

3
rashok

Dua alternatif bourne-ish di mana tidak memerlukan array bash:

Kasus 1 : Tetap bagus dan sederhana: Gunakan NewLine sebagai Pemisah Rekam ... mis.

IN="[email protected]
[email protected]"

while read i; do
  # process "$i" ... eg.
    echo "[email:$i]"
done <<< "$IN"

Catatan: dalam kasus pertama ini tidak ada sub-proses yang bercabang dua untuk membantu dengan manipulasi daftar.

Ide: Mungkin perlu menggunakan NL secara ekstensif internal , dan hanya mengonversi ke RS yang berbeda saat menghasilkan hasil akhir eksternal .

Kasus 2 : Menggunakan ";" sebagai pemisah rekaman ... mis.

NL="
" IRS=";" ORS=";"

conv_IRS() {
  exec tr "$1" "$NL"
}

conv_ORS() {
  exec tr "$NL" "$1"
}

IN="[email protected];[email protected]"
IN="$(conv_IRS ";" <<< "$IN")"

while read i; do
  # process "$i" ... eg.
    echo -n "[email:$i]$ORS"
done <<< "$IN"

Dalam kedua kasus, sub-daftar dapat dikomposisikan dalam loop tetap-menerus setelah loop selesai. Ini berguna saat memanipulasi daftar dalam memori, alih-alih menyimpan daftar dalam file. {p.s. tetap tenang dan lanjutkan B-)}

2
NevilleDNZ

Jika tidak ada ruang, Kenapa tidak?

IN="[email protected];[email protected]"
arr=(`echo $IN | tr ';' ' '`)

echo ${arr[0]}
echo ${arr[1]}
2
ghost

Terlepas dari jawaban fantastis yang sudah disediakan, jika itu hanya masalah mencetak data yang dapat Anda pertimbangkan menggunakan awk:

awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"

Ini mengatur pemisah bidang ke ;, sehingga ia dapat mengulangi bidang dengan loop for dan mencetaknya.

Uji

$ IN="[email protected];[email protected]"
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
> [[email protected]]
> [[email protected]]

Dengan input lain:

$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;c   d;e_;f"
> [a]
> [b]
> [c   d]
> [e_]
> [f]
1
fedorqui

Oke teman-teman!

Inilah jawaban saya!

DELIMITER_VAL='='

read -d '' F_ABOUT_DISTRO_R <<"EOF"
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
NAME="Ubuntu"
VERSION="14.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.4 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
EOF

SPLIT_NOW=$(awk -F$DELIMITER_VAL '{for(i=1;i<=NF;i++){printf "%s\n", $i}}' <<<"${F_ABOUT_DISTRO_R}")
while read -r line; do
   SPLIT+=("$line")
done <<< "$SPLIT_NOW"
for i in "${SPLIT[@]}"; do
    echo "$i"
done

Mengapa pendekatan ini "yang terbaik" bagi saya?

Karena dua alasan:

  1. Anda tidak tidak perlu melarikan diri pembatas;
  2. Anda tidak akan memiliki masalah dengan ruang kosong . Nilai akan dipisahkan dengan benar dalam array!

[]

1
Eduardo Lucio
IN='[email protected];[email protected];Charlie Brown <[email protected];!"#$%&/()[]{}*? are no problem;simple is beautiful :-)'
set -f
oldifs="$IFS"
IFS=';'; arrayIN=($IN)
IFS="$oldifs"
for i in "${arrayIN[@]}"; do
echo "$i"
done
set +f

Keluaran:

[email protected]
[email protected]
Charlie Brown <[email protected]
!"#$%&/()[]{}*? are no problem
simple is beautiful :-)

Penjelasan: Penugasan sederhana menggunakan tanda kurung () mengonversi daftar yang dipisahkan titik koma ke dalam array asalkan Anda memiliki IFS yang benar saat melakukan itu. Loop FOR standar menangani masing-masing item dalam array itu seperti biasa. Perhatikan bahwa daftar yang diberikan untuk variabel IN harus "keras" dikutip, yaitu, dengan kutu tunggal.

IFS harus disimpan dan dipulihkan karena Bash tidak memperlakukan penugasan dengan cara yang sama seperti perintah. Solusi alternatif adalah untuk membungkus tugas di dalam suatu fungsi dan memanggil fungsi itu dengan IFS yang dimodifikasi. Dalam hal itu tidak diperlukan penyimpanan/pemulihan IFS secara terpisah. Terima kasih untuk "Bize" karena menunjukkannya.

1
ajaaskel

Di Android Shell, sebagian besar metode yang diusulkan tidak berfungsi:

$ IFS=':' read -ra ADDR <<<"$PATH"                             
/system/bin/sh: can't create temporary file /sqlite_stmt_journals/mksh.EbNoR10629: No such file or directory

Apa yang berhasil adalah:

$ for i in ${PATH//:/ }; do echo $i; done
/sbin
/vendor/bin
/system/sbin
/system/bin
/system/xbin

di mana // berarti penggantian global.

1

Gunakan set bawaan untuk memuat larik [email protected]:

IN="[email protected];[email protected]"
IFS=';'; set $IN; IFS=$' \t\n'

Lalu, biarkan pesta dimulai:

echo $#
for a; do echo $a; done
ADDR1=$1 ADDR2=$2
1
jeberle

Mungkin bukan solusi yang paling elegan, tetapi bekerja dengan * dan spasi:

IN="[email protected] me.com;*;[email protected]"
for i in `delims=${IN//[^;]}; seq 1 $((${#delims} + 1))`
do
   echo "> [`echo $IN | cut -d';' -f$i`]"
done

Keluaran

> [[email protected] me.com]
> [*]
> [[email protected]]

Contoh lain (pembatas di awal dan akhir):

IN=";[email protected] me.com;*;[email protected];"
> []
> [[email protected] me.com]
> [*]
> [[email protected]]
> []

Pada dasarnya menghapus setiap karakter selain ; membuat delims misalnya. ;;;. Maka itu for loop dari 1 ke number-of-delimiters seperti yang dihitung oleh ${#delims} Langkah terakhir adalah mendapatkan bagian $ith dengan aman menggunakan cut.

0
Petr Újezdský

Satu baris untuk memisahkan string yang dipisahkan oleh ';' menjadi sebuah array adalah:

IN="[email protected];[email protected]"
ADDRS=( $(IFS=";" echo "$IN") )
echo ${ADDRS[0]}
echo ${ADDRS[1]}

Ini hanya menetapkan IFS dalam sebuah subkulit, sehingga Anda tidak perlu khawatir tentang menyimpan dan mengembalikan nilainya.

0
Michael Hale

Ini bahkan akan menangani spasi putih:

IFS=';' read ADDR1 ADDR2 <<< $(echo ${IN})
0
Mat Bess