複数のbash配列のよりエレガントな並列反復

複数のbash配列のよりエレガントな並列反復

CSVファイルから収集されたデータを処理するスクリプトを作成しています。データを複数の配列(ファイルの各列に1つの配列)として読み込みました。これで、実際にすべてのデータを順次処理する必要があります。

現在私はこれをしています:

# Read in the data:
declare -a DATACOL1 DATACOL2 RAWDATA
RAWDATA=($( sed '1d' /path/to/data.csv )) # Remove the header line
for line in ${RAWDATA[@]}; do
   declare -a LINEDATA LINE
   LINE=$( echo "$line" | sed 's/,/ /g' )
   for field in LINE; do
       LINEDATA+=("${field}")
   done
   DATACOL1+=(${LINEDATA[0]})
   DATACOL2+=(${LINEDATA[1]})
done


# Work on the data:
for i in $( seq 0 $[${#DATACOL1[@]}-1}; do
   stuff and things with ${DATACOL1[i]} and ${DATACOL2[i]}
done

私の(最も相互に関連している)質問は2つあります。

  • データを繰り返すよりもデータを処理するよりエレガントな方法はありますかfor i in $( seq 0 $[${#DATACOL1[@]}-1}?動作しますが醜いです。

  • CSVデータを取得するためのよりエレガントな方法はありますか?

これはbash 3にあるので、連想配列はありません。

答え1

私は次のように書くでしょう:

mapfile -t rawdata < <(sed 1d /path/to/data.csv)
datacol1=()
datacol2=()

for line in "${rawdata[@]}"; do
    IFS=, read -ra fields <<< "$line"
    datacol1+=( "${fields[0]}" )
    datacol2+=( "${fields[1]}" )
done

for ((i=0; i < "${#datacol1[@]}"; i++)); do
    stuff with "${datacol1[i]}" and "${datacol2[i]}"
done
  • mapfileファイルの行を配列として読み取るために使用されます。
  • とを使用して、行からカンマ区切りのフィールドを読みます IFSread
    • 引用符付き文字列はカンマで区切られます。実際のCSVパーサーを使用してください
  • forseq 呼び出しを避けるために、C と同様の形式を使用します。

もちろん、2番目のループやdatacol *変数は必要ありません。

for line in "${rawdata[@]}"; do
    IFS=, read -a fields <<< "$line"
    stuff with "${fields[0]}" and "${fields[1]}"
done

Bash 3ではそのような機能がないので、mapfilewhileループを使用してください。

datacol1=()
datacol2=()
while IFS=, read -ra fields; do
    datacol1+=("${fields[0]}")
    datacol2+=("${fields[1]}")
done < <(sed 1d /path/to/data.csv)

関連情報