根据密钥从文件中读取最近的条目
Reading recent entry from a file based on a key
输入文件,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
这适用于输入文件中的少量数据。我有 200 000 个条目并观察到 cut 命令非常慢。也尝试使用 awk,但没有得到更好的结果。我的要求是从 row1 读取文件,key 为 column1。我需要更新每个键的条目。
我认为使用 Awk
可以很容易地完成此操作,您只需要在 </code> 中散列 <code>
的值,一旦您使用 [=14= 分隔文件] 分隔符
awk -v FS=, -v OFS=, '{key[]=; 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?
在 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
使用GNU的最短的datamash
:
datamash -st, -g1 last 2 <file
g1
- 按第一列分组
last 2
- 保留组的最后一个值
输出:
FEB,APPLE
JAN,ORANGE
MAR,APPLE
输入文件,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
这适用于输入文件中的少量数据。我有 200 000 个条目并观察到 cut 命令非常慢。也尝试使用 awk,但没有得到更好的结果。我的要求是从 row1 读取文件,key 为 column1。我需要更新每个键的条目。
我认为使用 Awk
可以很容易地完成此操作,您只需要在 </code> 中散列 <code>
的值,一旦您使用 [=14= 分隔文件] 分隔符
awk -v FS=, -v OFS=, '{key[]=; 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?
在 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
使用GNU的最短的datamash
:
datamash -st, -g1 last 2 <file
g1
- 按第一列分组last 2
- 保留组的最后一个值
输出:
FEB,APPLE
JAN,ORANGE
MAR,APPLE