如何在Bash中解析CSV文件?

时间:2010-11-26 15:20:32

标签: linux bash csv

我正在研究一个很长的Bash脚本。我想将CSV文件中的单元格读入Bash变量。我可以解析行和第一列,但不能解析任何其他列。到目前为止,这是我的代码:


  cat myfile.csv|while read line
  do
    read -d, col1 col2 < <(echo $line)
    echo "I got:$col1|$col2"
  done

它只打印第一列。作为额外的测试,我尝试了以下内容:

read -d, x y < <(echo a,b,)

$ y是空的。所以我试过了:

read x y < <(echo a b)

$ y是b。为什么呢?

5 个答案:

答案 0 :(得分:171)

您需要使用IFS代替-d

while IFS=, read -r col1 col2
do
    echo "I got:$col1|$col2"
done < myfile.csv

请注意,对于通用CSV解析,您应该使用专门的工具来处理带有内部逗号的引用字段,以及Bash无法自行处理的其他问题。此类工具的示例包括cvstoolcsvkit

答案 1 :(得分:7)

来自man页面:

  

-d delim           delim的第一个字符用于终止输入行,   而不是新行。

您正在使用-d,,它将终止逗号上的输入行。它不会读取剩余的行。这就是为什么$ y是空的。

答案 2 :(得分:1)

我们可以用带引号的字符串来解析csv文件,并用say | |分隔。使用以下代码

while read -r line
do
    field1=$(echo $line | awk -F'|' '{printf "%s", $1}' | tr -d '"')
    field2=$(echo $line | awk -F'|' '{printf "%s", $2}' | tr -d '"')

    echo $field1 $field2
done < $csvFile

awk将字符串字段解析为变量,tr删除引号。

每个字段执行awk时速度稍慢。

答案 3 :(得分:0)

如果您想用一些行来读取CSV文件,那么这就是解决方案。

while IFS=, read -ra line
do 
    test $i -eq 1 && ((i=i+1)) && continue
    for col_val in ${line[@]}
    do
        echo -n "$col_val|"                 
    done
    echo        
done < "$csvFile"

答案 4 :(得分:-1)

除了@Dennis Williamson 的回答之外,跳过包含 CSV 标题的第一行可能会有所帮助:

{
  read
  while IFS=, read -r col1 col2
  do
    echo "I got:$col1|$col2"
  done 
} < myfile.csv