【问题标题】:Update column in file based on associative array value in bash根据bash中的关联数组值更新文件中的列
【发布时间】:2021-09-09 18:24:57
【问题描述】:

所以我有一个名为 testingFruits.csv 的文件,其中包含以下列:

name,value_id,size
apple,1,small
mango,2,small
banana,3,medium
watermelon,4,large

我还有一个关联数组存储以下数据:

fruitSizes[apple] = xsmall
fruitSizes[mango] = small
fruitSizes[banana] = medium
fruitSizes[watermelon] = xlarge

我是否可以根据关联数组中“名称”列中每个值的数据更新文件中的“大小”列?

我尝试过使用 awk,但没有运气。这是我尝试做的一个示例:

awk -v t="${fruitSizes[*]}" 'BEGIN{n=split(t,arrayval,""); ($1 in arrayval) {$3=arrayval[$1]}' "testingFruits.csv"

我知道这个命令会得到 bash 定义的数组fruitSizes,对所有值进行拆分,然后检查第一列(名称)是否在 fruitSizes 数组中。如果是,那么它将使用在fruitSizes 中找到的该特定名称的值更新第三列(大小)。

不幸的是,这给了我以下错误:

参数列表太长

这是我希望在同一个 testingFruits.csv 文件中的预期输出:

name,value_id,size
apple,1,xsmall
mango,2,small
banana,3,medium
watermelon,4,xlarge

我想处理的一个极端情况是 name 列中存在重复值,而 value_id 和 size 列的值不同。

【问题讨论】:

  • 仅供参考,将 bash 关联数组作为起点可能是个坏主意,因为它们速度慢且不可移植,并且使脚本的其余部分更难实现,您应该改用 awk 来读取您从中填充该数组的任何输入。

标签: bash awk


【解决方案1】:

如果您想坚持使用 awk 脚本,请通过标准输入传递数组以避免遇到 ARG_MAX 问题。

由于您的数组是关联的,因此仅列出 ${fruitSizes[@]} 是不够的。您还需要 keys ${!fruitSizes[@]}pr -2 可以将键值对在一行中。
这假定 ${fruitSizes[@]}${!fruitSizes[@]} expand in the same order,并且您的键和值没有字段分隔符(在本例中为 ,)。

printf %s\\n "${!fruitSizes[@]}" "${fruitSizes[@]}" | pr -t -2 -s, |
awk -F, -v OFS=, 'NR==FNR {a[$1]=$2; next} $1 in a {$3=a[$1]} 1' - testingFruits.csv

但是,我想知道数组 fruitSizes 来自哪里。如果您从文件或类似文件中读取它,则完全省略数组并在 awk 中执行所有操作会更容易。

【讨论】:

  • {a[$1]=$2;的意义是什么?下一个}?
  • @confusedcoder21 afruitSizes 的 awk 版本。我们需要上述规则来填充该数组。 NR==FNR 仅在第一个“文件”处激活(- 代表标准输入)。 a[$1]=$2 将来自 fruitSizes 的键 ($1) 和值 ($2) 存储在 awk 数组 a 中。 next 跳过所有其他 awk 规则并转到下一行。因此,$1 in a {$3=a[$1]} 1 部分仅针对第二个文件执行。 1{print} 的简写。
  • 所以 $1 指的是fruitSizes 中的键,$2 指的是值。而后面的 $3 指的是文件中的 size 列?
  • 如果我有更多列,这将如何改变?假设名称列是第 7 列,而大小列是第 13 列?
  • 没错。列的含义从“文件”(stdin -)更改为文件(testingFruits.csv)。如果您想修改此脚本,只需忽略NR==FNR {a[$1]=$2; next} 部分。这只是数组的“神奇”初始化。之后发生的事情可以随心所欲地改变。如果名称为$7,大小为$13,则使用$7 in a {$13=a[$7]} 1。之前的部分保持不变。
猜你喜欢
  • 1970-01-01
  • 2013-08-16
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
相关资源
最近更新 更多