使用 BASH 将带有嵌入逗号的值从数组写入 CSV 文件

使用 BASH 将带有嵌入逗号的值从数组写入 CSV 文件

我正在尝试将不同的数组写入 csv 文件 ($file) 列中。
每个数组都有相同数量的值。例如,arr1 和 arr2 各有 3 个值

arr1=( 23 45 34 )
arr2=( "abc,d"  ef  g )

我尝试了以下代码,但得到了错误的结果

for i in "${!arr1[@]}"; do
echo  "${arr1[i]}, ${arr2[i]}"  >> $file
done

我得到以下结果,其中 col1、col2 和 col3 是 3 列。

col1    col2    col3
23      "abc    d"
45       ef 
34       g

但期望的结果是

col1    col2   
23      "abc,d"
45       ef 
34       g

似乎“abc,d”中嵌入的彗差造成了问题。有人知道解决这个问题的方法或有更好的方法吗?

先感谢您!

答案1

从您的问题中不清楚您如何查看文件(也许使用电子表格程序?),但是 shell 可能会剥离数组定义中的引号:如果您希望以兼容 CSV 的方式处理嵌入的逗号,您应该将它们添加为文字引号,例如。

arr1=( 23 45 34 )
arr2=( \"abc,d\"  ef  g )

这样 shell 的内部表示看起来像

$ declare -p arr1 arr2
declare -a arr1=([0]="23" [1]="45" [2]="34")
declare -a arr2=([0]="\"abc,d\"" [1]="ef" [2]="g")

那么例如

for i in "${!arr1[@]}"; do 
  printf '%s,%s\n' "${arr1[i]}" "${arr2[i]}"
done > "$file"

结果是

$ cat "$file"
23,"abc,d"
45,ef
34,g

另一种选择是引用所有字段,例如。

arr1=( 23 45 34 )
arr2=( "abc,d"  ef  g )

for i in "${!arr1[@]}"; do 
  printf '"%s","%s"\n' "${arr1[i]}" "${arr2[i]}"
done > "$file"

给予

$ cat "$file"
"23","abc,d"
"45","ef"
"34","g"

答案2

此答案假设您的数据不包含文字选项卡。

首先为每个数组创建一个简单的列(带标题),然后使用 组合它们paste,创建一个 TSV 数据流:

#!/bin/bash

arr1=( 23 45 34 )
arr2=( abc,d ef g )

paste <( echo col1; printf '%s\n' "${arr1[@]}" ) \
      <( echo col2; printf '%s\n' "${arr2[@]}" )

其输出将读取

col1    col2
23      abc,d
45      ef
34      g

然后您可以使用 Miller 将其转换为正确引用的 CSV:

#!/bin/bash

arr1=( 23 45 34 )
arr2=( abc,d ef g )

paste <( echo col1; printf '%s\n' "${arr1[@]}" ) \
      <( echo col2; printf '%s\n' "${arr2[@]}" ) | mlr --t2c cat

这会生成

col1,col2
23,"abc,d"
45,ef
34,g

... CSV 感知程序将读取为

第 1 列 列2
23 A B C D
45 埃夫
34 G

支持 CSV 的电子表格程序也可能能够读取 TSV 数据,因此并不严格需要 Miller。

相关内容