web-dev-qa-db-fra.com

Fractionnement d'une chaîne par la première occurrence d'un délimiteur

J'ai une chaîne au format suivant

id;some text here with possible ; inside

et souhaitez le diviser en 2 chaînes par première occurrence de ;. Donc, ce devrait être: id et some text here with possible ; inside

Je sais diviser la chaîne (par exemple, avec cut -d ';' -f1), mais il se divisera en plusieurs parties puisque j'ai ; à l'intérieur de la partie gauche.

57
gakhov

cut ressemble à un outil approprié pour cela:

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

Mais read est encore plus adapté:

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
74
manatwork

Avec tout sh standard (y compris bash):

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

Les solutions basées sur read fonctionneraient pour les valeurs à caractère unique (et avec certains shells, à un octet) de $sep autre que l'espace, la tabulation ou la nouvelle ligne et uniquement si $s ne contient pas de caractères de nouvelle ligne.

cut les solutions basées ne fonctionneraient que si $s ne contient pas de caractères de nouvelle ligne.

sed des solutions pourraient être conçues pour gérer tous les cas d'angle avec une valeur de $sep, mais cela ne vaut pas la peine d'aller aussi loin quand il y a un support intégré dans le Shell pour cela.

18
Stéphane Chazelas

Comme vous l'avez mentionné, vous souhaitez affecter les valeurs à id et string

assignez d'abord votre motif à une variable (disons str)

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

Maintenant, vous avez vos valeurs dans les variables respectives

6
user1678213

En plus des autres solutions, vous pouvez essayer quelque chose basé sur regex:

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

ou en fonction de ce que vous essayez de faire exactement, vous pouvez utiliser

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

\1 et \2 contient les deux sous-chaînes que vous vouliez.

4
tojrobinson

Solution en 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
3
ethaning