여러 bash 배열의 보다 우아한 병렬 반복

여러 bash 배열의 보다 우아한 병렬 반복

CSV 파일에서 수집된 일부 데이터를 처리하는 스크립트를 작성 중입니다. 데이터를 여러 배열(파일의 각 열에 대해 하나의 배열)로 읽었습니다. 이제 실제로 모든 데이터를 순차적으로 처리해야 합니다.

현재 나는 이것을하고 있습니다 :

# 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

내 (가장 상호 연관되어 있는) 질문은 두 가지입니다.

  • 데이터를 반복하는 것보다 데이터를 처리하는 더 우아한 방법이 있습니까 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파일의 행을 배열로 읽는 데 사용됩니다 .
  • 및를 사용하여 줄에서 쉼표로 구분된 필드를 읽습니다 IFS.read
    • 인용된 문자열에서 쉼표로 구분됩니다.실제 CSV 파서를 사용하세요.
  • forseq 호출을 피하기 위해 C와 유사한 형식을 사용하십시오.

물론 두 번째 루프나 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)

관련 정보