Kaip suskirstyti eilutę pagal ribotuvą bash?

Turiu šią eilutę išsaugoti kintamajame:

 IN="bla@some.com;john@home.com" 

Dabar norėčiau atskirti eilutes atskiriant ; taip, kad turiu:

 ADDR1="bla@some.com" ADDR2="john@home.com" 

Man nebūtinai reikia kintamųjų ADDR1 ir ADDR2 . Jei jie yra dar geresni masyvo elementai.


Po toliau pateiktų atsakymų pasiūlymų aš baigiau:

 #!/usr/bin/env bash IN="bla@some.com;john@home.com" mails=$(echo $IN | tr ";" "\n") for addr in $mails do echo "> [$addr]" done 

Išvada:

 > [bla@some.com] > [john@home.com] 

Buvo pateiktas sprendimas, susijęs su „ Internal_field_separator“ (IFS) nustatymu ; . Nesu tikras, kas atsitiko su šiuo atsakymu, kaip vėl sugrąžino IFS į numatytuosius?

RE: IFS sprendimas, aš jį išbandžiau ir jis veikia, išsaugoju senus IFS ir tada atkuriu:

 IN="bla@some.com;john@home.com" OIFS=$IFS IFS=';' mails2=$IN for x in $mails2 do echo "> [$x]" done IFS=$OIFS 

Beje, kai bandžiau

 mails2=($IN) 

Pirmoji eilutė, kai spausdinau kilpa, be skliaustų aplink $IN gavo darbą.

1509
28 мая '09 в 5:03 2009-05-28 05:03 nustatė stefanB gegužės 28 d. '09, 05:03 am. 2009-05-28 05:03
@ 34 atsakymai
  • 1
  • 2

Galite nustatyti vidinį lauko separatoriaus (IFS) kintamąjį ir leisti jį analizuoti į masyvą. Kai tai įvyksta komandoje, tada IFS priskyrimas vyksta tik šioje aplinkoje su viena komanda (iki read ). Tada jis analizuoja įvestį pagal masyvo IFS kintamojo vertę, kurią mes galime perjungti.

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

Analizuojama viena atskirtų elementų eilutė ; spustelėdami jį į masyvą. Perdirbimo medžiaga yra tik $IN , kiekvieną kartą, kai viena įvesties eilutė yra atskiriama simboliu ; :

  while IFS=';' read -ra ADDR; do for i in "${ADDR[@]}"; do # process "$i" done done <<< "$IN" 
923
28 мая '09 в 5:23 2009-05-28 05:23 atsakė Johannes Schaub - litb gegužės 28 d

Paimta iš „ Bash shell“ scenarijaus padalijimo matricos :

 IN="bla@some.com;john@home.com" arrIN=(${IN//;/ }) 

Paaiškinimas:

Ši konstrukcija pakeičia visus ';' įvykius. (pradinis // reiškia visuotinį pakeitimą) IN eilutėje su ' ' (viena erdvė) ir tada interpretuoja erdvę, kuri yra ribota, kaip masyvą (tai yra aplinkiniai skliausteliai).

border=0

Sintaksė, naudojama garbanotose skliausteliuose, yra pakeisti kiekvieną simbolį ';' Simbolis ' ' vadinamas parametrų išplėtimu .

Yra keletas bendrų klaidų:

  • Jei šaltinio eilutėje yra tarpų, turėsite naudoti IFS :
    • IFS=':'; arrIN=($IN); unset IFS;
  • Jei šaltinio eilutėje yra tarpų, o ribotuvas yra nauja eilutė, galite nustatyti IFS su:
    • IFS=$'\n'; arrIN=($IN); unset IFS;
744
10 марта '11 в 12:00 2011-03-10 12:00 atsakymas pateikiamas palindromui kovo 10 d. 11 val. 12:00 2011-03-10 12:00

Jei nenorite, kad juos būtų galima apdoroti nedelsiant, man tai patinka:

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

Šią kilpą galite naudoti, kad būtų galima inicijuoti masyvą, tačiau tai greičiausiai yra paprastesnis būdas tai padaryti. Tikiuosi, kad tai padės.

207
28 мая '09 в 5:09 2009-05-28 05:09 Atsakymą pateikė Chris Lutz , gegužės 28 d., 05:09, 2009-05-28 05:09

Suderinamas atsakymas

Šiuo klausimu SO jau turi daug kitų būdų tai padaryti . Bet bash turi daug specialių bruožų, vadinamųjų bashismų , kurie veikia gerai, tačiau jis neveiks jokiame kode .

Visų pirma, masyvai, asociatyviosios matricos ir pakaitos simboliai yra gryni bazizmai ir gali neveikti kitose korpusuose.

Mano Debian GNU / Linux sistemoje yra standartinis apvalkalas, vadinamas , tačiau žinau daug žmonių, kurie mėgsta naudoti ksh .

Galiausiai, labai nedidelėje situacijoje yra specialus įrankis, su korpuso vertėjais ( ).

Prašoma eilutė

Nagrinėjama pavyzdžio eilutė SO:

 IN="bla@some.com;john@home.com" 

Kadangi tai gali būti naudinga tarpų, ir kadangi tarpai gali pakeisti subroutino rezultatą, aš norėčiau naudoti šią apytikslę eilutę:

  IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>" 

Padalinkite eilutę pagal ribotuvą (versija> = 4.2)

Naudodami švarų bash, galime naudoti masyvus ir IFS:

 var="bla@some.com;john@home.com;Full Name <fulnam@other.org>" 

 oIFS="$IFS" IFS=";" declare -a fields=($var) IFS="$oIFS" unset oIFS 

 IFS=\; read -a fields <<<"$var" 

Naudojant šią sintaksę naujausiame „bash“ nepakeičia dabartinės sesijos $IFS , bet tik dabartinei komandai:

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

Dabar eilutė var yra padalinta ir saugoma masyve (su pavadinimo fields ):

 set | grep ^fields=\\\|^var= fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>") var='bla@some.com;john@home.com;Full Name <fulnam@other.org>' 

Mes galime pateikti užklausą dėl kintamo turinio naudojant declare -p :

 declare -p var fields declare -- var="bla@some.com;john@home.com;Full Name <fulnam@other.org>" declare -a fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>") 

read yra greičiausias būdas padalinti, nes nėra šakių ir išorinių išteklių.

Iš ten galite naudoti sintaksę, kurią jau žinote, kad tvarkytumėte kiekvieną lauką:

 for x in "${fields[@]}";do echo "> [$x]" done > [bla@some.com] > [john@home.com] > [Full Name <fulnam@other.org>] 

po kiekvieno apdorojimo (arba man patinka šis perjungimo metodas):

 while [ "$fields" ] ;do echo "> [$fields]" fields=("${fields[@]:1}") done > [bla@some.com] > [john@home.com] > [Full Name <fulnam@other.org>] 

arba netgi paprastam spausdinimui (trumpesnė sintaksė):

 printf "> [%s]\n" "${fields[@]}" > [bla@some.com] > [john@home.com] > [Full Name <fulnam@other.org>] 

Padalinkite eilutę pagal

Bet jei rašote kažką tinkamo naudoti daugelyje kriauklių, neturėtumėte naudoti bachizmo.

Daugelyje kriauklių naudojama sintaksė, skirta eilutės padalijimui į pirmąjį ar paskutinį teksto rodinį:

 ${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 

(Tai yra pagrindinė mano atsakymo paskelbimo priežastis.)

Kaip nurodyta „ Score_Under“ :

# ir % ištrina trumpiausią atitinkamą eilutę ir

## ir %% ištrina didžiausią galimą laiką.

Šis mažas pavyzdinis scenarijus veikia gerai pagal „ bash“ , „ , „ , „ ir buvo išbandytas „Mac OS bash“:

 var="bla@some.com;john@home.com;Full Name <fulnam@other.org>" while [ "$var" ] ;do iter=${var%%;*} echo "> [$iter]" [ "$var" = "$iter" ]  \ var='' || \ var="${var#*;}" done > [bla@some.com] > [john@home.com] > [Full Name <fulnam@other.org>] 

Sėkmės!

121
13 апр. Atsakymas pateikiamas F. Hauri 13 Bal 2013-04-13 17:20 '13, 17:20, 2013-04-13 17:20

Kaip apie šį požiūrį:

 IN="bla@some.com;john@home.com" set -- "$IN" IFS=";"; declare -a Array=($*) echo "${Array[@]}" echo "${Array[0]}" echo "${Array[1]}" 

Šaltinis

80
28 мая '09 в 13:31 2009-05-28 13:31 atsakymas duotasis kaltintojas gegužės 28 d. '09 1:31 2009-05-28 13:31

Aš pamačiau keletą atsakymų, susijusių su cut , bet jie visi buvo ištrinti. Tai šiek tiek keista, kad niekas apie tai nekalbėjo, nes manau, kad tai yra viena iš naudingiausių šios rūšies dalykų komandų, ypač išnagrinėjus atskirtus žurnalo failus.

Jei šis konkretus pavyzdys padalijamas į masyvą, „bash“ scenarijus tikriausiai yra efektyvesnis, bet cut gali būti naudojamas ir efektyvesnis, jei norite ištraukti tam tikrus laukus iš vidurio.

Pavyzdys:

 $ echo "bla@some.com;john@home.com" | cut -d ";" -f 1 bla@some.com $ echo "bla@some.com;john@home.com" | cut -d ";" -f 2 john@home.com 

Akivaizdu, kad jį galite įdėti į kilpą ir pereiti per -f parinktį, kad kiekvienas laukas būtų traukiamas savarankiškai.

Tai tampa naudingesnė, jei turite ribotą žurnalo failą su tokiomis linijomis:

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

cut labai patogu, kad galėtumėte cat šį failą pasirinkti ir pasirinkti konkretų lauką tolesniam apdorojimui.

74
27 апр. DougW atsakymas pateiktas balandžio 27 d 2015-04-27 21:20 '15, 21:20, 2015-04-27 21:20

Jis dirbo man:

 string="1;2" echo $string | cut -d';' -f1 # output is 1 echo $string | cut -d';' -f2 # output is 2 
65
11 авг. Steven Lizarazo atsakymas 11 rug . 2016-08-11 23:45 '16 at 11:45 pm 2016-08-11 23:45
 echo "bla@some.com;john@home.com" | sed -e 's/;/\n/g' bla@some.com john@home.com 
59
28 мая '09 в 5:12 2009-05-28 05:12 atsakė į „ Lothar “ gegužės 28 d., 05:12, 2009-05-28 05:12

Ji taip pat veikia:

 IN="bla@some.com;john@home.com" echo ADD1=`echo $IN | cut -d \; -f 1` echo ADD2=`echo $IN | cut -d \; -f 2` 

Būkite atsargūs, šis sprendimas ne visada teisingas. Jei perduosite tik „bla@some.com“, jis paskirs ir ADD1, ir ADD2.

57
08 сент. Atsakymą pateikė Ashok 08 Sep 2012-09-08 08:01 '12 at 8:01 am 2012-09-08 08:01

Manau, AWK yra geriausia ir efektyviausia komanda, kuri išspręs jūsų problemą. „AWK“ yra įtraukta į „Bash“ pagal nutylėjimą beveik visuose „Linux“ platinimuose.

 echo "bla@some.com;john@home.com" | awk -F';' '{print $1,$2}' 

duos

 bla@some.com john@home.com 

Žinoma, galite išsaugoti kiekvieną el. Pašto adresą, nepaisydami awk spausdinimo lauko.

32
14 янв. Atsakymas suteiktas Tony 14 jan. 2013-01-14 09:33 '13 ne 9:33 2013-01-14 09:33

Kitas požiūris į Darrono atsakymą , kaip tai padaryti:

 IN="bla@some.com;john@home.com" read ADDR1 ADDR2 <<<$(IFS=";"; echo $IN) 
25
05 июля '11 в 16:41 2011-07-05 16:41 atsakymas pateikiamas nickjb liepos 5 d. 11 d. 4:41 pm 2011-07-05 16:41

„Bash“ brošiūroje veikiantis būdas, net jei jūsų kintamasis turi naujus eilutės simbolius:

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

Išvaizda:

 $ 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")' 

Šio tikslo tikslas yra naudoti „ -d read option“ (ribotuvą) su tuščiu ribotuvu, todėl read privaloma perskaityti viską, ką jis maitino. Ir mes suskaičiuojame į kintamojo turinį, be „ribinės naujos linijos“ dėka printf . Atkreipkite dėmesį, kad mes taip pat įterpiame spausdintuvo printf kad įsitikintume, jog read eilutė turi galinį ribotuvą. Be jo, read galimus tuščius laukus:

 $ in='one;two;three;' # there 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]="")' 

likęs tuščias laukas išsaugomas.


„Bash“ naujinimas ≥4,4

Kadangi „Bash 4.4“, integruota mapfile (dar žinoma kaip „ readarray ) palaiko -d skirtą nurodyti separatorių. Todėl dar vienas kanoninis būdas:

 mapfile -d ';' -t array < <(printf '%s;' "$in") 
23
26 июня '14 в 12:11 2014-06-26 12:11 atsakymą pateikė gniourf_gniourf birželio 26 d., 14 val. 12:11 2014-06-26 12:11

Tai turėtų veikti visur:

 echo "luke;yoda;leila" | tr ";" "\n" 

(Atkreipkite dėmesį, kad šis metodas yra verta, jei esate naujas „Bash“ ir jums reikia tiesiog paprasto ir trumpo triuko. Akademinis ir „teisingas“ būdas yra naudoti IFS, kaip nurodyta kituose pranešimuose.)

22
03 дек. Avt'W atsakymas 03 dec. 2017-12-03 03:40 '17 at 3:40 2017-12-03 03:40

Kaip apie šį vieną linijinį laivą, jei nenaudojate masyvų:

 IFS=';' read ADDR1 ADDR2 <<<$IN 
18
13 сент. Atsakymą pateikė Darron rugsėjo 13 d 2010-09-13 23:10 '10, 11:10 val. 2010-09-13 23:10

Be IFS nustatymo

Jei turite tik vieną dvitaškį, galite tai padaryti:

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

gausite:

 b = foo c = bar 
16
01 авг. atsakymą pateikė Emilien Brigand 01 rug. 2016-08-01 16:15 '16, 16:15 pm 2016-08-01 16:15

Čia yra švarus 3 linijinis:

 in="foo@bar;bizz@buzz;fizz@buzz;buzz@woof" IFS=';' list=($in) for item in "${list[@]}"; do echo $item; done 

kur IFS riboja žodžius pagal ribotuvą, ir () naudojamas masyvui sukurti. Tada [@] naudojamas kiekvienam elementui grąžinti kaip atskirą žodį.

Jei po to turite bet kokį kodą, jūs taip pat turite atkurti, pavyzdžiui, $IFS . unset IFS .

14
11 сент. atsakymas suteiktas kenorb 11 sep . 2015-09-11 23:54 '15 , 11:54 val. 2015-09-11 23:54

Yra paprastas ir aiškus būdas:

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

Bet jūs turite naudoti gnu xargs, BSD xargs negali palaikyti -d delim. Jei naudojatės obuoliu, kaip ir aš. Galite įdiegti gnu xargs:

 brew install findutils 

tada

 echo "add:sfff" | gxargs -d: -i echo {} 
7
16 сент. Victor Choy atsakymas rugsėjo 16 d 2015-09-16 06:34 '15 at 6:34 2015-09-16 06:34

Toliau pateikta „Bash / zsh“ funkcija suskirsto savo pirmąjį argumentą ant antrojo argumento nurodyto ribotuvo:

 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 } 

Pavyzdžiui, komanda

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

suteikia

 a b c 

Pavyzdžiui, šis išėjimas gali būti perduotas kitoms komandoms. Pavyzdys:

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

Palyginti su kitais gautais sprendimais, jis turi šiuos privalumus:

  • IFS nepaisoma: dėl dinamiškos net vietinių kintamųjų aprėpties IFS cikle sukelia naujos vertės tekėjimą į funkcijų skambučius, kurie atliekami ciklo viduje.

  • Lėkštės nenaudojamos: eilutės skaitymas į masyvą naudojant read reikalauja „flag“ Bash ir -a in zsh.

Jei pageidaujate, funkcija gali būti įdėta į scenarijų taip:

 #!/usr/bin/env bash split() { # ... } split "$@" 
4
24 мая '17 в 11:42 2017-05-24 11:42 atsakymą įteikė Halle Knast gegužės 17 d

Tai paprasčiausias būdas tai padaryti.

 spo='one;two;three' OIFS=$IFS IFS=';' spo_array=($spo) IFS=$OIFS echo ${spo_array[*]} 
4
25 сент. atsakymą pateikė „ Prospero 25 sep“. 2011-09-25 04:09 '11 at 4:09 2011-09-25 04:09
 IN="bla@some.com;john@home.com" IFS=';' read -a IN_arr <<< "${IN}" for entry in "${IN_arr[@]}" do echo $entry done 

Išeiti

 bla@some.com john@home.com 

Sistema: Ubuntu 04.04.1

3
25 окт. Atsakyti rashok Oct 25. 2016-10-25 15:41 '16 at 15:41 pm 2016-10-25 15:41

galite taikyti awk daugeliu atvejų

 echo "bla@some.com;john@home.com"|awk -F';' '{printf "%s\n%s\n", $1, $2}' 

taip pat galite tai naudoti

 echo "bla@some.com;john@home.com"|awk -F';' '{print $1,$2}' OFS="\n" 
3
20 янв. atsakymas shuaihanhungry 20 jan. 2018-01-20 18:54 '18 18:54 2018-01-20 18:54

Jei nėra vietos, kodėl gi ne?

 IN="bla@some.com;john@home.com" arr=(`echo $IN | tr ';' ' '`) echo ${arr[0]} echo ${arr[1]} 
2
24 апр. atsakymas pateikiamas vaiduoklis 24 balandis. 2013-04-24 16:13 '13, 16:13, 2013-04-24 16:13

Čia yra keletas įdomių atsakymų (klaidinga versija), bet kažkas panašaus į skaidymą kitomis kalbomis - tai aš supratau pradiniame klausime - nusprendžiau:

 IN="bla@some.com;john@home.com" declare -aa="(${IN/;/ })"; 

Dabar ${a[0]} , ${a[1]} ir tt, kaip tikitės. Naudokite ${#a[*]} terminų skaičiui. Arba, žinoma, pakartokite:

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

SVARBI PASTABA:

Tai veikia tais atvejais, kai nerimaujama dėl problemų, kurios išsprendė mano problemą, bet gali neišspręsti jūsų problemos. Šiuo atveju pereikite prie „ $IFS sprendimo.

2
22 окт. atsakymas duotas eukras 22 okt. 2012-10-22 10:10 '12, 10:10 am 2012-10-22 10:10

Geri vaikinai!

Čia yra mano atsakymas!

 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 

Kodėl man toks požiūris yra „geriausias“?

Dėl dviejų priežasčių:

  • Nereikia paslėpti separatoriaus;
  • Jūs neturite problemų su tarpais . Vertė bus tinkamai padalyta į masyvą!

[]

1
04 апр. Atsakyti Eduardo Lucio 04 Bal 2016-04-04 22:54 '16 at 22:54 pm 2016-04-04 22:54

Dvi bourne-ish alternatyvos, kai bazinių matricų nereikia:

1 atvejis : laikykite jį gražus ir paprastas: naudokite NewLine kaip įrašų atskyriklį, pvz.

 IN="bla@some.com john@home.com" while read i; do # process "$i" ... eg. echo "[email:$i]" done <<< "$IN" 

Pastaba: šiuo pirmuoju atveju subprocesas nėra naudojamas palaikyti sąrašo manipuliavimą.

Idėja: gali būti verta naudoti NL viduje ir tik perskaičiuojant į kitą RS, kai sukuriate galutinį rezultatą iš išorės.

2 atvejis : naudojant „;“ kaip įrašų atskyriklis ... pvz.

 NL=" " IRS=";" ORS=";" conv_IRS() { exec tr "$1" "$NL" } conv_ORS() { exec tr "$NL" "$1" } IN="bla@some.com;john@home.com" IN="$(conv_IRS ";" <<< "$IN")" while read i; do # process "$i" ... eg. echo -n "[email:$i]$ORS" done <<< "$IN" 

Abiem atvejais sub-sąrašas gali būti sudarytas cikle, kuris yra pastovus po ciklo pabaigos. Tai naudinga manipuliuojant atmintyje esančiais sąrašais, o ne failų sąrašuose. {Prenumerata išlaikykite ramybę ir tęskite B-}}

1
02 сент. Atsakymas yra pateiktas NevilleDNZ 02 rugsėjis. 2013-09-02 09:30 '13, 09:30, 2013-09-02 09:30

Naudokite įmontuotą set kad įkeltumėte $@ masyvą:

 IN="bla@some.com;john@home.com" IFS=';'; set $IN; IFS=$' \t\n' 

Tada paleiskite šalį:

 echo $# for a; do echo $a; done ADDR1=$1 ADDR2=$2 
1
30 апр. atsakymas duotas 30 bal . 2013-04-30 06:10 '13, 6:10, 2013-04-30 06:10

„Android“ korpuse dauguma siūlomų metodų tiesiog neveikia:

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

Kas yra darbas:

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

kur // reiškia visuotinį pakeitimą.

1
20 февр. Atsakymas pateiktas 18446744073709551615 20 vasaris 2015-02-20 13:49 '15 at 13:49 2015-02-20 13:49

Be fantastinių atsakymų, kurie jau buvo pateikti, jei tai tik duomenų įtraukimo klausimas, galite naudoti „ awk :

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

Tai nustato lauko separatorių ; taip, kad jis galėtų eiti per laukus su kilpa ir atitinkamai spausdinti.

Bandymas

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

Su kitu įvedimu:

 $ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;cd;e_;f" > [a] > [b] > [cd] > [e_] > [f] 
1
08 янв. atsakymą pateikė fedorqui 08 sausis 2015-01-08 13:21 '15, 13:21 pm 2015-01-08 13:21

Galbūt tai nėra elegantiškiausias sprendimas, tačiau jis veikia su * ir tarpais:

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

Rezultatai

 > [bla@so me.com] > [*] > [john@home.com] 

Kitas pavyzdys (atskyrikliai pradžioje ir pabaigoje):

 IN=";bla@so me.com;*;john@home.com;" > [] > [bla@so me.com] > [*] > [john@home.com] > [] 

Jis iš esmės ištrina visus kitus simbolius, išskyrus ; pavyzdžiui, delims . ;;; . Tada jis atlieka kilpą nuo 1 iki number-of-delimiters , skaičiuojant pagal ${#delims} . Paskutinis žingsnis yra saugiai gauti $i dalį su cut .

0
26 февр. Atsakymą pateikė Petr Újezdský 26 vasaris. 2016-02-26 15:20 '16 at 15:20 2016-02-26 15:20
 IN='bla@some.com;john@home.com;Charlie Brown <cbrown@acme.com;!"#$% 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 

Išvada:

 bla@some.com john@home.com Charlie Brown <cbrown@acme.com !"#$% are no problem simple is beautiful :-) 

Paaiškinimas: Paprastas priskyrimas naudojant laikiklį () konvertuoja kabliataškiais suskirstytą sąrašą į masyvą, jei turite teisingą IFS. Standartinė FOR linija apdoroja atskirus šio masyvo elementus kaip įprasta. Atkreipkite dėmesį, kad kintamajam IN nurodytas sąrašas turi būti „kietas“, t.y. Su vieninteliu tonu.

IFS turi būti išsaugotas ir atkurtas, nes „Bash“ netaikoma tikslui ir komandai. Alternatyvus problemos sprendimas - užduotis priskirti funkcijai ir šią funkciją pavadinti modifikuotu IFS. Tokiu atveju nebūtina atskirai išsaugoti / atstatyti IFS. Dėkojame už „bize“ už tai, kad nurodėte.

0
10 окт. spalio 10 d. atsakė ajaaskel . 2014-10-10 14:33 '14, 14:33 2014-10-10 14:33
  • 1
  • 2

Kiti klausimai apie „ arba „ Užduoti klausimą“