web-dev-qa-db-ja.com

シェルスクリプトで文字列を配列に変換する方法

私はすでに読んだ 文字列をbashの配列に分割する方法 ですが、質問は少し違うようですので、データを使用して質問します。

STDINからのこの行があります。

(5,[a,b,c,d,e,f,g,h,i,j])

5つは私のグループIDで、文字は配列(グループデータ)の値です。グループIDをvarに、文字をIFS=',' read -r -a array <<< "$tline"を使用して作業できるものに取得する必要があります

5
Magno C
_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"
_

説明:

  • 最初に、デフォルト/現在のバックアップを取ります Shell IFS with _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の配列に要素を追加/削除する方法

8
αғsнιη
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
<
3
Kusalananda

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' "$@"

改行文字を含むものでも、グループデータフィールドの任意の値で機能する必要があります。

2

データのフォーマットを考えると、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を含む配列を出力します。

0
J. Starnes