BASH - 如何从CSV文件的列中提取数据并将其放入数组中?

8

我正在学习Bash脚本。

我有一个带有5列和22行的CSV文件。我想要将第二列的数据提取出来并放入一个数组中。

我希望第一个名字在array[0],第二个名字在array[1]等等。

Bash脚本:

#!/bin/sh
IFS=","
eCollection=( $(cut -d ',' -f2 MyAssignment.csv ) )
printf "%s\n" "${eCollection[0]}"

CSV文件长成这个样子。没有带有标题的行。
我想将包含“Vl18xx”号码的列拆分成一个数组。
John,Vl1805,VRFname,10.9.48.64/28,10.9.48.78 
John,Vl1806,VRFname,10.9.48.80/28,10.9.48.94
John,Vl1807,VRFname,10.9.48.96/28,10.9.48.110 
John,Vl1808,VRFname,10.9.48.112/28,10.9.48.126
John,Vl1809,VRFname,167.107.152.32/28,167.107.152.46

这个 bash 脚本没有将第二列放入数组中,我做错了什么?

1
请取消您的IFS分配。 - Adam Burry
4个回答

14

移除IFS=","赋值,从而让默认的IFS值(空格、制表符、换行符)应用。

#!/bin/bash

eCollection=( $(cut -d ',' -f2 MyAssignment.csv ) )
printf "%s\n" "${eCollection[0]}"

说明:变量eCollection是一个数组,因为有外部括号。它通过来自$(cut -d ',' -f2 MyAssignment.csv)子shell的每个元素进行初始化,这个子shell使用了cut命令和','分隔符,从MyAssignment.csv文件中打印第二个字段-f2printf语句只是展示了如何按索引打印任何项,你也可以尝试echo "${eCollection[@]}"来查看所有元素。

6
如果存在空格,即“New York”,那么这个答案将会遇到问题。 - Paradise
1
如果CSV文件中有带逗号的引用字段,这样做不会出错吗? - Liron Yahdav
是的,字段中的空格会成为一个问题。但是问题中的数据没有包含空格。我想要实现的是最简单可行的代码。 - Adam Burry
1
我理解这个答案解决了问题,这也是为什么它有很多赞,但它缺乏对语法的适当解释,这使得初学者难以从中学习。 - user91991993

11

两种纯bash解决方案:

eCollection=()
while IFS=',' read -r _ second _; do
    eCollection+=("$second")
done < file.txt
printf '%s\n' "${eCollection[0]}"


readarray -t eCollection < file.txt
eCollection=("${eCollection[@]#*,}")
eCollection=("${eCollection[@]%%,*}")
printf '%s\n' "${eCollection[0]}"

谢谢Aleks,我也会尝试您提出的解决方案。 - DMS

10
更好的方法是使用readarray。不需要考虑IFS可以具有任何值,并且安全免受路径名扩展的影响。
readarray -t eCollection < <(cut -d, -f2 MyAssignment.csv)
printf '%s\n' "${eCollection[0]}"

1
最后IFS让我很头疼,因为我的一个列包含了带有空格的数据。然后我尝试了你提出的方法,它非常有效!谢谢你! - DMS

0

我喜欢使用 awk。首先根据 , 分隔符进行分割,并将所需列值存入数组中。

abc=($(tail -n +1 MyAssignment.csv | awk -F ',' '{print $2;}'))
echo ${abc[1]}

索引从1开始。如果文件包含标题,请将+1替换为+2以忽略标题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接