BASH를 사용하여 배열에서 CSV 파일로 쉼표가 포함된 값 쓰기

BASH를 사용하여 배열에서 CSV 파일로 쉼표가 포함된 값 쓰기

csv 파일($file) 열에 다른 배열을 쓰려고 합니다.
각 배열에는 동일한 수의 값이 있습니다. 예를 들어 arr1과 arr2에는 각각 3개의 값이 있습니다.

arr1=( 23 45 34 )
arr2=( "abc,d"  ef  g )

다음 코드를 시도했지만 잘못된 결과가 나왔습니다.

for i in "${!arr1[@]}"; do
echo  "${arr1[i]}, ${arr2[i]}"  >> $file
done

col1, col2 및 col3이 3개의 열인 다음 결과를 얻습니다.

col1    col2    col3
23      "abc    d"
45       ef 
34       g

하지만 원하는 결과는

col1    col2   
23      "abc,d"
45       ef 
34       g

"abc,d"에 포함된 혼수 상태가 문제의 원인인 것 같습니다. 이 문제에 대한 해결책을 알고 있거나 더 나은 방법을 갖고 있는 사람이 있습니까?

미리 감사드립니다!

답변1

파일을 보는 방법(아마도 스프레드시트 프로그램을 사용합니까?)이 귀하의 질문에서 명확하지 않지만 쉘은 배열 정의에서 따옴표를 제거할 수 있습니다. 포함된 쉼표를 CSV 호환 방식으로 처리하려면 다음을 추가해야 합니다. 예를 들어 리터럴 인용문으로 사용됩니다.

arr1=( 23 45 34 )
arr2=( \"abc,d\"  ef  g )

따라서 쉘의 내부 표현은 다음과 같습니다.

$ declare -p arr1 arr2
declare -a arr1=([0]="23" [1]="45" [2]="34")
declare -a arr2=([0]="\"abc,d\"" [1]="ef" [2]="g")

예를 들어

for i in "${!arr1[@]}"; do 
  printf '%s,%s\n' "${arr1[i]}" "${arr2[i]}"
done > "$file"

밝혀지다

$ cat "$file"
23,"abc,d"
45,ef
34,g

또 다른 옵션은 모든 필드를 인용하는 것입니다.

arr1=( 23 45 34 )
arr2=( "abc,d"  ef  g )

for i in "${!arr1[@]}"; do 
  printf '"%s","%s"\n' "${arr1[i]}" "${arr2[i]}"
done > "$file"

주다

$ cat "$file"
"23","abc,d"
"45","ef"
"34","g"

답변2

이 답변에서는 데이터에 텍스트 탭이 포함되어 있지 않다고 가정합니다.

먼저 각 배열에 대한 간단한 열(헤더 포함)을 만든 후 다음을 사용하여 결합합니다 paste.

#!/bin/bash

arr1=( 23 45 34 )
arr2=( abc,d ef g )

paste <( echo col1; printf '%s\n' "${arr1[@]}" ) \
      <( echo col2; printf '%s\n' "${arr2[@]}" )

출력은 다음과 같습니다

col1    col2
23      abc,d
45      ef
34      g

그런 다음 Miller를 사용하여 이를 적절하게 인용된 CSV로 변환할 수 있습니다.

#!/bin/bash

arr1=( 23 45 34 )
arr2=( abc,d ef g )

paste <( echo col1; printf '%s\n' "${arr1[@]}" ) \
      <( echo col2; printf '%s\n' "${arr2[@]}" ) | mlr --t2c cat

이것은 생성됩니다

col1,col2
23,"abc,d"
45,ef
34,g

... CSV 인식 프로그램은 다음과 같이 읽습니다.

열 1 2열
이십 삼 ABCD
45 에브
34 G

CSV를 지원하는 스프레드시트 프로그램은 TSV 데이터도 읽을 수 있으므로 Miller가 꼭 필요한 것은 아닙니다.

관련 정보