如何在 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

我使用上面的printfwithreadarray来避免在字符串末尾添加换行符(<<<"$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]
}'

相关内容