Dividere la stringa per la prima occorrenza di un delimitatore


54

Ho una stringa nel prossimo formato

id;some text here with possible ; inside

e vuoi dividerlo in 2 stringhe per prima occorrenza di ;. Quindi, dovrebbe essere: idesome text here with possible ; inside

So come dividere la stringa (per esempio, con cut -d ';' -f1), ma si dividerà in più parti poiché ho ;all'interno la parte sinistra.


Dopo che la stringa è stata divisa, cosa vuoi fare con "id"? Vuoi assegnarlo a una variabile, stamparlo, ecc.?
Daemon of Chaos,

Avrò 2 variabili: idestring
gakhov il

Risposte:


65

cut sembra uno strumento adatto per questo:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"
id

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

Ma readè ancora più adatto:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"
id

bash-4.2$ echo "$string"
some text here with possible ; inside

3
Grande! Esso funziona magicamente! Selezionerò il readdato che sto usando bash. Grazie @manatwork!
gakhov,

L' cutapproccio funzionerà solo quando "$ s" non contiene caratteri di nuova riga. leggi è in qualsiasi shell tipo Bourne. <<< è in rc, zsh e versioni recenti di bash e ksh93 ed è quello che non è standard.
Stéphane Chazelas,

Oops, hai ragione @StephaneChazelas. La mia mente era a -aper qualche ragione quando si citano bash'il read. (Evidentemente inutile qui.)
Manatwork

Ho dimenticato di dire che l'approccio di lettura non funziona se $ s contiene anche caratteri di nuova riga. Ho aggiunto la mia risposta.
Stéphane Chazelas,

1
Vorrei sottolineare il trattino finale -f 2-nel string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"comando. Questo è ciò che ignora il resto dei delimitatori nella stringa per la stampa. Non ovvio se si guarda la pagina man dicut
Steen il

18

Con qualsiasi sh standard (incluso bash):

sep=';'
case $s in
  (*"$sep"*)
    before=${s%%"$sep"*}
    after=${s#*"$sep"}
    ;;
  (*)
    before=$s
    after=
    ;;
esac

readle soluzioni basate funzionerebbero per valori a carattere singolo (e con alcune shell, a byte singolo) $sepdiversi da spazio, tabulazione o nuova riga e solo se $snon contengono caratteri di nuova riga.

cutle soluzioni basate funzionerebbero solo se $snon contengano caratteri di nuova riga.

sedpotrebbero essere escogitate soluzioni che gestiscono tutti i casi angolari con qualsiasi valore di $sep, ma non vale la pena andare così lontano quando c'è un supporto integrato nella shell per quello.


6

Come hai già detto, vuoi assegnare i valori a id e stringa

prima assegna il tuo pattern ad una variabile (diciamo str)

    str='id;some text here with possible ; inside'
    id=${str%%;} 
    string=${str#;}

Ora hai i tuoi valori nelle rispettive variabili


se stai ricevendo il tuo pattern da un comando, usa set - some_command, allora il tuo pattern verrà memorizzato in $ 1 e userà il codice sopra con 1 invece di str
user1678213

1
In che modo questa risposta è diversa da @StephaneChazelas?
Bernhard,

4

Oltre alle altre soluzioni, potresti provare qualcosa in regexbase:

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

o a seconda di cosa stai cercando di fare esattamente, potresti usare

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

dove \1e \2contenere le due sottostringhe che stavi cercando.


1

Soluzione in bash standard:

    text='id;some text here with possible ; inside'
    text2=${text#*;}
    text1=${text%"$text2"}

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.