web-dev-qa-db-ja.com

bashシェルで1つの文字列を複数の変数に分割する方法

私は解決策を探していて、似たような質問を見つけました。それらの間にスペースを置いて文を分割しようとしているだけで、答えは私の状況ではうまくいきません。

現在、変数は次のような文字列に設定されています。
ABCDE-123456
そして、私はそれを2つの変数に分けながら、「 -
var1=ABCDE
var2=123456

どのようにしてこれを達成することが可能ですか?


これは私のために働いた解決策です:
var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)

それを使用することは可能ですか カット 区切り文字なしで動作するコマンド(各文字は変数として設定されます)?

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

129

Ifあなたの解決策は一般的である必要はありません、すなわちあなたの例のような文字列に対して動作するだけでよい、あなたはすることができます:

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

ここでcutを選択したのは、コードをさらにいくつかの変数に拡張できるからです。

129
Rob I

readIFSはこれに最適です。

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

編集:

個々の文字を配列要素に読み込む方法は次のとおりです。

$ read -a foo <<<"$(echo "ABCDE-123456" | sed 's/./& /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")'

文字列にスペースがある場合

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

2つのフィールドになることがわかっている場合は、次のような追加のサブプロセスをスキップすることができます。

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

これは何をしますか? ${STR%-*}は、文字列の末尾からパターン$STRに一致する-*の最も短い部分文字列を削除します。 ${STR#*-}も同じですが、*-パターンを使用し、文字列の先頭から開始します。それぞれ対応する%%##があり、これらは最長固定パターンの一致を見つけます。どなたかが覚えておくと便利なニーモニックがあれば、教えてください。私はいつも覚えておくために両方を試す必要があります。

138
mkb

カスタムのsetを持つIFSの仕事のように思えます。

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

local IFSを持つ関数でこれを行いたいので、IFSを必要とするスクリプトの他の部分をめちゃくちゃにしないでください。)

35
tripleee

Bash正規表現機能を使う:

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

OUTPUT

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