我正在研究一个很长的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
。为什么呢?
答案 0 :(得分:171)
您需要使用IFS
代替-d
:
while IFS=, read -r col1 col2
do
echo "I got:$col1|$col2"
done < myfile.csv
请注意,对于通用CSV解析,您应该使用专门的工具来处理带有内部逗号的引用字段,以及Bash无法自行处理的其他问题。此类工具的示例包括cvstool
和csvkit
。
答案 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