bash에서 알 수 없는 값 개수로 문자열 CSV 변수를 잘라내고 해당 값을 반복하는 방법은 무엇입니까?

bash에서 알 수 없는 값 개수로 문자열 CSV 변수를 잘라내고 해당 값을 반복하는 방법은 무엇입니까?

이것은 쉬워 보일 수 있지만 이 문제에 갇혀 있습니다.

길이를 알 수 없는 항목이 포함된 CSV 문자열이 있습니다.

"item1,item2,item3,..."

잘라내고 해당 항목을 반복하고 싶습니다.

나는 시도했다:

while IFS=, read item;
do
   echo $item
done <<< $csvString

하지만 전체 문자열을 한 번만 제공합니다.

cut루프하는 방법을 찾을 수 없기 때문에 사용할 수 없습니다 .

답변1

read입력이 한 줄이고 한 번에 한 줄씩 읽히기 때문에 표시된 것처럼 반복할 수 없습니다 . 이 read작업은 첫 번째 필드와 모든 후속 필드를 사용자가 제공하는 단일 변수로 읽어옵니다.

입력 문자열 항목을 항목별로 처리하려면 각 항목을 배열 요소로 변환한 다음 해당 요소를 반복하면 됩니다.

readarray -d , -t csvArray < <( printf '%s' "$csvString" )

for item in "${csvArray[@]}"; do
    printf '%s\n' "$item"
done

나는 문자열 끝에 개행 문자를 추가하는 것을 피하기 위해 위의 printfwith를 사용합니다( 개행 문자가 추가됩니다).readarray<<<"$csvString"

그러나 입력 문자열이 쉼표로 구분된 간단한 하위 문자열 목록이 아닌 CSV 문자열인 경우 readarray일부 필드에 구분 기호가 포함되어 있을 수 있으므로 문자열을 올바르게 분할할 수 없습니다. Miller( )와 같은 CSV 인식 도구를 사용하여 mlr문자열을 구문 분석하고 원하는 작업을 수행할 수 있습니다.

$ csvString='"1, 2, 3",Hello world,A,B,C'
$ mlr --csv -N put -q 'for (k,v in $*) { emit v }' <<<"$csvString"
"1, 2, 3"
Hello world
A
B
C

mlr명령은 헤더 없는 단일 CSV 입력 레코드를 반복하여 각 필드의 값을 새 레코드로 출력합니다. Miller는 쉼표가 포함되어 있기 때문에 처음으로 방출된 레코드를 자동으로 인용합니다.

답변2

awk다음과 같이 사용할 수도 있습니다 ( $csvStringSimple-csv 형식의 문자열을 가정).

awk -v itmStr="$csvString" '
BEGIN{
       itmNr=split(itmStr, items, /,/)
       for (i=1; i<=itmNr; i++)
           print items[i]
}'

관련 정보