我正在尝试将一个csv文件读入到Bash关联数组中,但是得到的结果与我的期望不符。
使用Bash 5.0.18版本
Bellum:fox3-api rocky$ bash --version
GNU bash, version 5.0.18(1)-release (x86_64-apple-darwin19.5.0)
foobar.csv的内容
Bellum:scripts rocky$ cat ./foobar.csv
foo-1,bar-1
foo-2,bar-2
foo-3,bar-3
problem.sh的内容
#!/usr/bin/env bash
declare -A descriptions
while IFS=, read name title; do
echo "I got:$name|$title"
descriptions[$name]=$title
done < foobar.csv
echo ${descriptions["foo-1"]}
echo ${descriptions["foo-2"]}
echo ${descriptions["foo-3"]}
problem.sh 的实际输出
Bellum:scripts rocky$ ./problem.sh
I got:foo-1|bar-1
I got:foo-2|bar-2
bar-2
Bellum:scripts rocky$
期望输出:
I got:foo-1|bar-1
I got:foo-2|bar-2
I got:foo-3|bar-3
bar-1
bar-2
bar-3
评论请求输出
Bellum:scripts rocky$ head -n 1 ./foobar.csv | hexdump -C
00000000 ef bb bf 66 6f 6f 2d 31 2c 62 61 72 2d 31 0d 0a |...foo-1,bar-1..|
00000010
Bellum:scripts rocky$ od -c foobar.csv
0000000 357 273 277 f o o - 1 , b a r - 1 \r \n
0000020 f o o - 2 , b a r - 2 \r \n f o o
0000040 - 3 , b a r - 3
0000050
Cyrus的dos2unix修改
#!/usr/bin/env bash
declare -A descriptions
dos2unix < foobar.csv | while IFS=, read name title; do
echo "I got:$name|$title"
descriptions[$name]=$title
done
echo ${descriptions["foo-1"]}
echo ${descriptions["foo-2"]}
echo ${descriptions["foo-3"]}
Cyrus的dos2unix更改的输出
Bellum:scripts rocky$ ./problem.sh
I got:foo-1|bar-1
I got:foo-2|bar-2
Bellum:scripts rocky$
这个CSV文件是通过在Microsoft Excel中另存为CSV格式而在Mac上创建的。感谢提前任何见解。
混合解决方案
对于未来的读者,这个问题实际上有两个问题。首先,保存CSV文件时使用了Microsoft Excel for Mac工作簿。我选择 "CSV UTF-8" 格式(Excel下拉菜单中列出的第一个CSV文件格式)进行“另存为”。这会添加附加字节,这些字节会破坏bash中的read命令。有趣的是,这些字节在cat命令中不会显示(请参阅原始帖子中的问题描述)。改为在Excel中选择“逗号分隔值”(在格式的下拉列表中更靠后),就可以解决第一个问题。
其次,@Léa Gris和@glenn jackman指导我使用脚本修改符,以处理Excel文件中存在的一些换行符和回车符。
感谢大家。我花了整整一天的时间来解决这个问题。教训:我应该更早地求助于Stackoverflow。
while
循环后添加typeset -p descriptions
以查看完整的数组定义;也可以验证数据文件的内容 =>od -c foobar.csv
,然后检查输出是否有除\n
之外的非打印字符。 - markp-fusohead -n 1 ./foobar.csv | hexdump -C
的输出添加到您的问题中(无注释)。 - Cyrus357 273 277
的结果 - 看起来是“UTF-8字节顺序标记”;如果无法在从Excel保存文件时消除它,则有几个去除它的想法:这个 和 这个。 - markp-fuso