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

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

私が読んでBashで文字列を配列に分割する方法ところで、この質問は私とはちょっと違うようなので、私のデータを活用して質問してみましょう。

STDINには次の行があります。

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

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

答え1

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"

説明する:

  • まず、基本/現在をバックアップする必要があります。シェルIFSそしてbkpIFS="$IFS";
  • 次に、IFSを区切り文字セット、、、、,に設定します。これは、入力文字列を1つ以上の区切り文字で区切ることができることを意味します。()][IFS=',()]['

  • 次に、行を読み込み、上記で定義したIFSに基づいて着信入力文字列から呼び出されるread -r -a array配列に分割します。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これは、オプションreadなしで入力にバックスラッシュがあるために-r発生します。

  • echo ${array[@]}配列のすべての要素を印刷しています。バラより$*と$@の違いは何ですか?そしてザイルズの答え${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])"

説明する:

  • [...]繰り返しますが、using関数/[...]/の最新の実装でサポートされている正規表現定数で定義されている区切り文字グループに基づいて入力行全体を分割します。awksplitもっと読む機能セクションでsplit()

  • 次にEND{for (x in arr) printf ("%s ",arr[x]); ...}、配列を繰り返してarrその値を印刷します。xこれは以下を指します。索引配列arr要素。詳しくはこちらawkBEGIN/END ルール

次にサイドリダイレクトBashで配列に要素を追加/削除する方法は?

答え2

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[@]}"

これは、最初に標準入力に到着した入力データの合計をすべて削除し、コンマを改行に置き換え、()結果をに割り当てます。[]trdata

次に、それを使用してreadarrayこのデータを解析します。

最初の呼び出しでは、最初の項目(含む)のみが読み取られ、-n 1それが変数に割り当てられますgroup

2番目の呼び出しでは、readarray最初の項目(含む-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

POSIX的に:

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

グループデータフィールドのすべての値(改行文字を含む)に対して機能する必要があります。

答え4

ツールを使用して句読点を削除するsedと、その行から数字と文字のみを取得できます。

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

echo $a | sed 's/[[:punct:]]/ /g'

出力:

5  a b c d e f g h i j 

関連情報