私はすでに読んだ 文字列をbashの配列に分割する方法 ですが、質問は少し違うようですので、データを使用して質問します。
STDINからのこの行があります。
(5,[a,b,c,d,e,f,g,h,i,j])
5つは私のグループIDで、文字は配列(グループデータ)の値です。グループIDをvarに、文字をIFS=',' read -r -a array <<< "$tline"
を使用して作業できるものに取得する必要があります
_bkpIFS="$IFS"
IFS=',()][' read -r -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j])"
echo ${array[@]} ##Or printf "%s\n" ${array[@]}
5 a b c d e f g h i j
IFS="$bkpIFS"
_
説明:
bkpIFS="$IFS"
_;次に、IFSを区切り文字のセット_,
_、_(
_、_)
_、_]
_および_[
_にIFS=',()]['
を使用して設定します。これは、入力文字列を意味しますこれらの区切り文字の1つ以上で区切ることができます。
次に、_read -r -a array
_は、 Here-String メソッドで渡された入力文字列から上記の定義されたIFSのみに基づいて、array
という配列に行を読み取り、分割します。 _-r
_オプションは、read
コマンドが入力時にバックスラッシュ_\
_を展開しないように指示するために使用されます。
_IFS=',()][' read -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j,\,k])"
echo ${array[@]}
5 a b c d e f g h i j ,k
_
最後の_,k
_を参照してください。入力にバックスラッシュがあり、_-r
_オプションなしのread
が原因です。
_echo ${array[@]}
_では、配列のすべての要素を出力しています。詳細は $ *と$ @の違いは何ですか? および Gillesの答え について_${array[@]}
_を参照してください。
_printf "%s\n" ${array[@]}
_では、配列要素を出力する他の方法もあります。
これで、配列の特定の要素を_printf "%s\n" ${array[INDEX]}
_または_echo ${array[INDEX]}
_と同じように出力できます。
ああ、申し訳ありませんが、IFS
をシェルに返すのを忘れた、_IFS="$bkpIFS"
_:)
または、awk
とそのsplit
関数を使用します。
_awk '{split($0,arr,/[][,)(]/)}
END{for (x in arr) printf ("%s ",arr[x]);printf "\n"}' <<<"(5,[a,b,c,d,e,f,g,h,i,j])"
_
説明:
ここでも同じですが、awk
関数を使用したsplit
の最新の実装でサポートされている正規表現定数_[...]
_の区切り文字_/[...]/
_の定義されたグループに基づいて、入力行全体を分割しています。 もっと読むsplit()
関数のセクション。
次にEND{for (x in arr) printf ("%s ",arr[x]); ...}
では、arr
という配列をループして、対応する値を出力します。ここでx
は、配列arr
要素のindexを指します。 awk
のBEGIN/ENDルール の詳細をご覧ください。
サイドリダイレクト bashの配列に要素を追加/削除する方法 。
data=$(tr -d '[]()' | tr ',' '\n')
readarray -t -n 1 group <<<"$data"
readarray -t -s 1 letters <<<"$data"
printf 'group = %s\n' "$group"
printf 'data: %s\n' "${letters[@]}"
これにより、最初にtr
を使用して標準入力に到着する入力データからすべての()
と[]
が削除され、次にコンマが改行に置き換えられて結果が次のように割り当てられますdata
。
次に、readarray
を使用してこのデータを解析します。
最初の呼び出しでは、最初のエントリ(-n 1
付き)のみが読み取られ、変数group
に割り当てられます。
readarray
への2番目の呼び出しは、最初のエントリをスキップし(-s 1
を使用)、残りのエントリを配列letters
に割り当てます。
-t
は、各エントリから実際の改行を削除します。
ここではgroup
は配列ですが、1つの要素しか含まれていないため、$group
として使用できます。
$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
group = 5
data: a
data: b
data: c
data: d
data: e
data: f
data: g
data: h
data: i
data: j
次の例では、文字列内のコンマを保持し、readline
を使用してエントリを区切っていますが、何らかの理由で、letters
の最後の要素の最後に改行があります。
data=$(tr -d '[]()')
readarray -d, -t -s 1 letters <<<"$data"
printf '>%s<\n' "${letters[@]}"
ランニング:
$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
>a<
>b<
>c<
>d<
>e<
>f<
>g<
>h<
>i<
>j
<
POSIXly:
string='(5,[a,b,c,d,e,f,g,h,i,j])'
set -o noglob
IFS=',['
string=${string#'('}
string=${string%'])'}
set -- $string''
gid=$1; shift 2
printf '%s\n' "gid=$gid; group-data:"
printf ' <%s>\n' "$@"
改行文字を含むものでも、グループデータフィールドの任意の値で機能する必要があります。
データのフォーマットを考えると、read
はそれを配列にきれいに入れません。 sed
は、データを「クリーンアップ」するために使用できます。
declare -a TLINEARRAY
TLINEARRAY=($(sed -e 's/,/ /g' -e 's/\[/ /g' -e 's/\]//g' <<< "$tline" ))
echo ${TLINEARRAY[*]}
read
を試してみました。
read -a TLINEARRAY <<< "$(sed -e 's/,/ /g' -e 's/\[/ /g' -e 's/\]//g' <<< "$tline" )"
echo ${TLINEARRAY[*]}
どちらのメソッドも、5 a b c d e f g h i j
を含む配列を出力します。