从基于密钥的文件中读取最近的条目

问题描述 投票:3回答:3

输入文件fruits.txt:

JAN,APPLE 
FEB,MANGO 
JAN,ORANGE 
MAR,APPLE 
FEB,APPLE

预期的输出文件:

MAR,APPLE
FEB,APPLE
JAN,ORANGE

要获得上述输出,请使用以下代码:

#!/bin/sh

declare -A m_arr

cat fruits.txt > /tmp/ID.part

while read line
do
Month=$(echo $line | cut -d, -f1)
Fruits=$(echo $line | cut -d, -f2)
m_arr[${Month}]=${Fruits}
done < /tmp/ID.part

for i in ${!m_arr[@]}
do
echo "$i,${m_arr[$i]}"
done

这适用于输入文件中的少量数据。我有20万个条目,并观察到切割命令非常慢。也试过awk,没有得到更好的结果。我的要求是从row1读取文件,键为column1。我需要更新每个密钥的条目。

bash shell awk cut
3个回答
3
投票

我认为用Awk可以很容易地做到这一点,一旦你用$1分隔符分隔文件,你只需要在$2中散列,的值

awk -v FS=, -v OFS=, '{key[$1]=$2; next}END{for (i in key) print i,key[i]}' file

此外,如果您想在处理一百万行文件时加快速度,可以在解析时更改本地化设置以加快执行速度,您可以在本地将LC_ALL=C传递给命令。见Stéphane Chazelas's answer on what "LC_ALL=C" does?


3
投票

在bash版本4中,你可以声明一个关联数组,并用read的结果填充它,用自定义IFS分割你的行:

$ declare -A a
$ while IFS=, read key value; do a["$key"]="$value"; done < fruits.txt
$ declare -p a
declare -A a=([MAR]="APPLE" [FEB]="APPLE" [JAN]="ORANGE" )

如果要从数组生成特定输出,还需要循环:

$ for key in "${!a[@]}"; do printf '%s,%s\n' "$key" "${a[$key]}"; done
MAR,APPLE
FEB,APPLE
JAN,ORANGE

3
投票

使用GNU datamash的最短的:

datamash -st, -g1 last 2 <file
  • g1 - 第1栏组
  • last 2 - 保持该组的最后一个值

输出:

FEB,APPLE
JAN,ORANGE 
MAR,APPLE 
© www.soinside.com 2019 - 2024. All rights reserved.