IFS 不能很好地解析 CSV
IFS not parsing well CSV
我正在尝试解析文件以便获取第一列。我使用的命令是:
while IFS=',' read -r a; do echo "$a"; done < test.csv
但是它仍然输出整个 csv 而不是第一列。 csv的例子如下:
NOM,CODI,DATA,SEXE,GRUP_EDAT,RESIDENCIA,CASOS_CONFIRMAT,PCR,INGRESSOS_TOTAL,INGRESSOS_CRITIC,INGRESSATS_TOTAL,INGRESSATS_CRITIC,EXITUS
MOIANÃS,42,24/08/2020,Home,Majors de 74,No,0,2,0,0,0,0,0
ALT CAMP,01,30/07/2020,Dona,Entre 15 i 64,Si,0,0,0,0,0,0,0
ALT CAMP,01,30/07/2020,Dona,Entre 65 i 74,No,0,1,0,0,0,0,0
ALT CAMP,01,30/07/2020,Dona,Entre 65 i 74,Si,0,0,0,0,0,0,0
我一直在寻找其他地方,似乎所有人都同意这应该是使用 IFS 解析 csv 时的正确方法。我注意到的一件事是,如果我向读取函数添加一个新列,比如 b,它会输出第一列而不是所有内容。
while IFS=',' read -r a b; do echo "$a"; done < test.csv
我不明白这种行为,它似乎只打印第一列。例如,如果我输入 c 和 $c,它不会打印第三列等等。
你能解释一下这种行为以及为什么会这样吗?
谢谢
bash
不是解析 csv 文件的正确工具,为此您应该考虑 awk
。例如要打印前 2 列,请使用这个超级简单的 awk 命令:
awk -F, '{print , }' file.csv
只是为了强调您的问题:关于您的 bash
循环,最好使用数组将所有逗号分隔的列准备好放入数组中:
while IFS=, read -ra arr; do
# print first 2 columns
echo "col1=${arr[0]}, col2=${arr[1]}"
done < file.csv
read
工作正常。它在 IFS 上拆分并将每个字段分配给一个变量,该行的其余部分转到最后一个变量。如果你只给一个变量,整行都去。
对于简单 CSV 文件,您可以简单地拆分每个逗号,但您希望将输入读入数组,除非你知道每一行的列数。
例如,如果您知道(最多)10 列,您可以使用
while IFS=, read -r f1 f2 f3 f4 f5 f6 f7 f8 f9 f10; do
但是,在 bash
中,将整个拆分行读入单个 数组:
更简单
while IFS=, read -ra f; do
第一个字段是 "${f[0]}"
,第二个字段是 "${f[1]}"
,等等
我正在尝试解析文件以便获取第一列。我使用的命令是:
while IFS=',' read -r a; do echo "$a"; done < test.csv
但是它仍然输出整个 csv 而不是第一列。 csv的例子如下:
NOM,CODI,DATA,SEXE,GRUP_EDAT,RESIDENCIA,CASOS_CONFIRMAT,PCR,INGRESSOS_TOTAL,INGRESSOS_CRITIC,INGRESSATS_TOTAL,INGRESSATS_CRITIC,EXITUS
MOIANÃS,42,24/08/2020,Home,Majors de 74,No,0,2,0,0,0,0,0
ALT CAMP,01,30/07/2020,Dona,Entre 15 i 64,Si,0,0,0,0,0,0,0
ALT CAMP,01,30/07/2020,Dona,Entre 65 i 74,No,0,1,0,0,0,0,0
ALT CAMP,01,30/07/2020,Dona,Entre 65 i 74,Si,0,0,0,0,0,0,0
我一直在寻找其他地方,似乎所有人都同意这应该是使用 IFS 解析 csv 时的正确方法。我注意到的一件事是,如果我向读取函数添加一个新列,比如 b,它会输出第一列而不是所有内容。
while IFS=',' read -r a b; do echo "$a"; done < test.csv
我不明白这种行为,它似乎只打印第一列。例如,如果我输入 c 和 $c,它不会打印第三列等等。
你能解释一下这种行为以及为什么会这样吗?
谢谢
bash
不是解析 csv 文件的正确工具,为此您应该考虑 awk
。例如要打印前 2 列,请使用这个超级简单的 awk 命令:
awk -F, '{print , }' file.csv
只是为了强调您的问题:关于您的 bash
循环,最好使用数组将所有逗号分隔的列准备好放入数组中:
while IFS=, read -ra arr; do
# print first 2 columns
echo "col1=${arr[0]}, col2=${arr[1]}"
done < file.csv
read
工作正常。它在 IFS 上拆分并将每个字段分配给一个变量,该行的其余部分转到最后一个变量。如果你只给一个变量,整行都去。
对于简单 CSV 文件,您可以简单地拆分每个逗号,但您希望将输入读入数组,除非你知道每一行的列数。
例如,如果您知道(最多)10 列,您可以使用
while IFS=, read -r f1 f2 f3 f4 f5 f6 f7 f8 f9 f10; do
但是,在 bash
中,将整个拆分行读入单个 数组:
while IFS=, read -ra f; do
第一个字段是 "${f[0]}"
,第二个字段是 "${f[1]}"
,等等