これは簡単に見えるかもしれませんが、この問題に閉じ込められています。
長さが不明な項目を含むCSV文字列があります。
"item1,item2,item3,..."
切り取り、その項目を繰り返したいです。
私は試した:
while IFS=, read item;
do
echo $item
done <<< $csvString
しかし、文字列全体を一度だけ提供します。
cut
ループする方法が見つからないため使用できません。
答え1
read
入力が1行で一度に1行ずつ読み取られるため、示されているように繰り返すことはできません。このread
操作は、最初のフィールドとすべての後続のフィールドをユーザーが提供する単一の変数として読み取られます。
入力文字列項目を項目ごとに処理するには、各項目を配列要素に変換してからその要素を繰り返すだけです。
readarray -d , -t csvArray < <( printf '%s' "$csvString" )
for item in "${csvArray[@]}"; do
printf '%s\n' "$item"
done
私は文字列の末尾に改行文字を追加することを避けるために上記のprintf
withを使用します(改行文字が追加されます)。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
次のように使用することもできます($csvString
Simple-csv形式の文字列を想定しています)。
awk -v itmStr="$csvString" '
BEGIN{
itmNr=split(itmStr, items, /,/)
for (i=1; i<=itmNr; i++)
print items[i]
}'