将csv字符串读入bash数组
Posted
技术标签:
【中文标题】将csv字符串读入bash数组【英文标题】:Reading csv string into bash array 【发布时间】:2022-01-17 06:58:48 【问题描述】:以下函数使用awk
将一个csv 行转换为多行。然后我可以将输出分配给一个数组,以便能够访问这些字段。
function csv_to_lines()
echo $@ | awk '
BEGIN FPAT = "([^,]*)|(\"[^\"]+\")";
for(i=1; i<=NF; i++) printf("%s\n", $i)'
line='A,B,"C,D",E'
arr=($(csv_to_lines $line))
printf '%s,' "$arr[@]"
但是,这不适用于空字段。例如:
line='A,,,,,"C,D",E'
arr=($(csv_to_lines $line))
printf '%s,' "$arr[@]"
输出
A,"C,D",E,
但我期待
A,,,,,"C,D",E,
显然,当分配给数组时,所有空行都会被忽略。如何创建一个保留空行的数组?
【问题讨论】:
在 awkprintf("%s\n", $i)
= print $i
。您的脚本中还有一些 shell 错误,将其复制/粘贴到 shellcheck.net 会告诉您。
【参考方案1】:
当前代码:
$ line='A,,,,,"C,D",E'
$ csv_to_lines $line
A
"C,D"
E
查看我们看到的实际生成的字符:
$ csv_to_lines $line | od -c
0000000 A \n \n \n \n \n " C , D " \n E \n
0000016
arr=(...)
将在空白处分割这些数据并将可打印的字符存储在数组中,实际上是这样做的:
$ arr=(A
"C,D"
E)
$ typeset -p arr
declare -a arr=([0]="A" [1]="C,D" [2]="E")
$ printf '%s,' "$arr[@]"
A,"C,D",E,
在数组中存储“空白行”的几个想法:
使用mapfile
将每一行读入数组,例如:
$ mapfile -t arr < <(csv_to_lines $line)
$ typeset -p arr
declare -a arr=([0]="A" [1]="" [2]="" [3]="" [4]="" [5]="\"C,D\"" [6]="E")
或者让awk
使用\n
以外的东西作为分隔符,然后定义一个自定义的IFS
将函数结果解析到数组中,例如:
$ function csv_to_lines() echo $@ | awk '
BEGIN FPAT = "([^,]*)|(\"[^\"]+\")";
for(i=1; i<=NF; i++) printf("%s|", $i)';
$ csv_to_lines $line
A|||||"C,D"|E|
$ IFS='|' arr=($(csv_to_lines $line))
$ typeset -p arr
declare -a arr=([0]="A" [1]="" [2]="" [3]="" [4]="" [5]="\"C,D\"" [6]="E")
这两种情况都会导致:
$ printf '%s,' "$arr[@]"
A,,,,,"C,D",E,
【讨论】:
mapfile
解决方案是完美的。如果 csv 在其中一个字段中包含 |
,则使用 |
之类的字符会遇到问题。以上是关于将csv字符串读入bash数组的主要内容,如果未能解决你的问题,请参考以下文章
BASH - 从 csv 文件的行创建数组,其中第一个条目是数组名称
BASH - 如何从 CSV 文件中的列中提取数据并将其放入数组中?