BASH - 从 csv 文件的行创建数组,其中第一个条目是数组名称
Posted
技术标签:
【中文标题】BASH - 从 csv 文件的行创建数组,其中第一个条目是数组名称【英文标题】:BASH - Create arrays from lines of csv file, where first entry is array name 【发布时间】:2022-01-12 10:43:11 【问题描述】:我正在学习在 Bash 中编写脚本。 我有一个 CSV 文件,其中包含下一行:
numbers,one,two,three,four,five
colors,red,blue,green,yellow,white
custom-1,a,b,c,d,e
custom+2,t,y,w,x,z
需要从这里创建数组,其中第一个条目是数组名称,例如。
number=(one,two,three,four,five)
colors=(red,blue,green,yellow,white)
custom-1=(a,b,c,d,e)
custom+2=(t,y,w,x,z)
这是我的脚本:
IFS=","
while read NAME VALUES ; do
declare -a $NAME
arrays+=($NAME)
IFS=',' read -r -a $NAME <<< "$VALUES[0]"
done < file.csv
当我尝试使用仅包含两个第一个字符串(数字和颜色)的 csv 文件时,代码运行良好。如果我尝试使用数字、颜色、custom-1、custom-2,读取 csv 时会出错:
./script.sh: line 5: declare: `custom-1': not a valid identifier
./script.sh: line 7: read: `custom+2': not a valid identifier
据我所知,因为 bash 不允许在变量名中使用特殊字符。有什么办法可以避免吗?
【问题讨论】:
没有。您必须重命名变量。 Bash 也没有嵌套数组。而且不能把数组变成哈希值。 您的第一个数组应命名为numbers
,而不是number
。并且 bash 变量不能有任何名称。忘记custom-1
或custom+2
,它们是无效的变量名,如错误消息所述。修改这些名称以使其成为有效的变量名称,或者使用例如计数器创建有效的数组名称,并将您感兴趣的名称存储为关联数组的键,其中值将是计数器。这样您就可以从第一列的文本中恢复真正的数组名称。
【参考方案1】:
由于您不能将 CSV 文件的第一列用作 bash 数组名称,因此一个选项是使用计数器生成有效名称(例如 arrayN
)。如果您想使用第一列的值访问您的数据,您还需要将它们存储在具有相应计数器值的某个位置。关联数组 (declare -A names=()
) 将是完美的。最后但同样重要的是,namerefs(declare -n arr=...
,从 bash 4.3 开始可用)将方便存储和访问您的数据。示例:
declare -i cnt=1
declare -A names=()
while IFS=',' read -r -a line; do
names["$line[0]"]="$cnt"
declare -n arr="array$cnt"
unset line[0]
declare -a arr=( "$line[@]" )
((cnt++))
done < foo.csv
现在,要访问对应于条目custom+2
的值,首先获取相应的计数器值,声明一个指向相应数组的nameref,然后瞧:
$ cnt="$names[custom+2]"
$ declare -n arr="array$cnt"
$ echo "$arr[@]"
t y w x z
让我们声明一个函数以便于访问:
getdata ()
local -i cnt="$names[$1]"
local -n arr="array$cnt"
[ -z "$2" ] && echo "$arr[@]" || echo "$arr[$2]"
然后:
$ getdata "custom+2"
t y w x z
$ getdata "colors"
red blue green yellow white
$ getdata "colors" 3
yellow
【讨论】:
declare -n
很有用,但需要 bash 4.3
@Fravadona 对。我为此添加了一条注释,谢谢。以上是关于BASH - 从 csv 文件的行创建数组,其中第一个条目是数组名称的主要内容,如果未能解决你的问题,请参考以下文章
BASH - 如何从 CSV 文件中的列中提取数据并将其放入数组中?
使用 bash (sed/awk) 提取 CSV 文件中的行和列?