web-dev-qa-db-fra.com

Comment diviser une chaîne en plusieurs variables dans un shell bash?

Je cherchais une solution et trouvais des questions similaires. Seulement, ils essayaient de scinder des phrases avec des espaces entre eux et les réponses ne fonctionnaient pas pour ma situation.

Actuellement, une variable est définie sur une chaîne, comme ceci:
ABCDE-123456
et je voudrais scinder cela en 2 variables, en éliminant le "-". c'est à dire.:
var1=ABCDE
var2=123456

Comment est-il possible d'accomplir cela?


C'est la solution qui a fonctionné pour moi:
var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)

Est-il possible d'utiliser le couper commande qui fonctionnera sans délimiteur (chaque caractère est défini comme une variable)?

var1=$(echo $STR | cut -f1 -d?)
var2=$(echo $STR | cut -f1 -d?)
var3=$(echo $STR | cut -f1 -d?)
etc.

134

Si votre solution ne doit pas nécessairement être générale, c’est-à-dire qu’elle ne doit fonctionner que pour des chaînes comme votre exemple, vous pouvez faire:

var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)

J'ai choisi cut ici parce que vous pourriez simplement étendre le code pour un peu plus de variables ...

134
Rob I

read avec IFS sont parfaits pour cela:

$ IFS=- read var1 var2 <<< ABCDE-123456
$ echo "$var1"
ABCDE
$ echo "$var2"
123456

Edit:

Voici comment vous pouvez lire chaque caractère individuel dans des éléments de tableau:

$ read -a foo <<<"$(echo "ABCDE-123456" | sed 's/./& /g')"

Dump le tableau:

$ declare -p foo
declare -a foo='([0]="A" [1]="B" [2]="C" [3]="D" [4]="E" [5]="-" [6]="1" [7]="2" [8]="3" [9]="4" [10]="5" [11]="6")'

S'il y a des espaces dans la chaîne:

$ IFS=$'\v' read -a foo <<<"$(echo "ABCDE 123456" | sed 's/./&\v/g')"
$ declare -p foo
declare -a foo='([0]="A" [1]="B" [2]="C" [3]="D" [4]="E" [5]=" " [6]="1" [7]="2" [8]="3" [9]="4" [10]="5" [11]="6")'
171

Si vous savez qu'il ne s'agira que de deux champs, vous pouvez ignorer les sous-processus supplémentaires comme ceci:

var1=${STR%-*}
var2=${STR#*-}

Qu'est-ce que cela fait? ${STR%-*} supprime la sous-chaîne la plus courte de $STR correspondant au modèle -* à partir de la fin de la chaîne. ${STR#*-} fait la même chose, mais avec le motif *- et à partir du début de la chaîne. Ils ont chacun leurs contreparties %% et ## qui trouvent la correspondance de motif ancré la plus longue. Si quelqu'un a un mnémonique utile pour se rappeler lequel fait quoi, faites le moi savoir! Je dois toujours essayer les deux pour me souvenir.

144
mkb

Cela ressemble à un travail pour set avec un personnalisé IFS.

IFS=-
set $STR
var1=$1
var2=$2

(Vous voudrez faire cela dans une fonction avec un local IFS afin de ne pas gâcher les autres parties de votre script où vous exigez que IFS soit ce que vous attendez.)

38
tripleee

Utilisation des fonctionnalités bash regex:

re="^([^-]+)-(.*)$"
[[ "ABCDE-123456" =~ $re ]] && var1="${BASH_REMATCH[1]}" && var2="${BASH_REMATCH[2]}"
echo $var1
echo $var2

SORTIE

ABCDE
123456
22
anubhava
string="ABCDE-123456"
IFS=- # use "local IFS=-" inside the function
set $string
echo $1 # >>> ABCDE
echo $2 # >>> 123456
15
Archibald