这看起来似乎很容易,但我却被困在这个问题上。
我有一个 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
我使用上面的printf
withreadarray
来避免在字符串末尾添加换行符(<<<"$csvString"
会添加换行符)。
但是,如果您的输入字符串是 CSV 字符串,而不是逗号分隔的子字符串的简单列表,则您不能依赖readarray
正确拆分字符串,因为某些字段可能包含嵌入的分隔符。您可以使用支持 CSV 的工具(例如 Miller ( 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]
}'