假设我们有两个示例文件。第一个文件填充了通过组合名字的前两个字符和姓氏的最后 2 个字符创建的唯一员工姓名。Example : Peter Smith - Peht
第一个文件包含:
Peht
Mawo
Stso
Makr
Bavo
第二个文件包含他们登录系统时的记录。 (显然还有未列出的员工file1
。)
第二个文件:
Mawo 21.4.2016 17:49
Peht 21.4.2016 17:58
Mawo 22.4.2016 7:58
Wato 22.4.2016 7:59
Stso 22.4.2016 8:02
Bavo 22.4.2016 8:15
Bane 22.4.2016 9:01
Bavo 23.4.2016 9:12
Mawo 23.4.2016 9:24
Dalo 23.4.2016 9:54
Peht 23.4.2016 9:58
Grma 24.4.2016 10:00
我需要找出 file1 中的员工连接到系统的次数 (
file2
)。
最好的方法是什么?我想到的唯一解决方案是进行一些 2 个循环,对于file1
循环整个file2
thengrep
名称中的每个名称,询问名称是否匹配(如果是则那么)count++
。任何人都可以给我一些优雅的解决方案来解决这个问题,例如awk
如果可能的话?
答案1
一些简单的事情,比如:
mapfile -t names < file1
for name in "${names[@]}"
do
echo "${name}" $(grep -c "^$name " file2)
done
将提供如下输出:
Peht 2
Mawo 3
Stso 1
Makr 0
Bavo 2
grep 字符串表示将用户名锚定在行的开头 (^),并在行后强制添加尾随空格。
答案2
测试.awk:
FNR == NR{
names[$1]
next
}
($1 in names){
ulog[$1]++
}
END{
for(name in ulog){
print name ":" ulog[name]
}
}
并将其运行为
awk -f test.awk user.list user.log
FNR==NR # 文件记录号==记录号,如果是那么我们仍然在第一个文件
next # 因为我们仍在第一个文件中,所以跳过其余部分并拉入下一行
其余的应该是不言自明的
或作为单行
awk 'FNR == NR{ names[$1]; next } ($1 in names){ ulog[$1]++ } END{ for(name in ulog){ print name ":" ulog[name] } }' user.list user.log
答案3
这是 // 的另join
一种sort
方式uniq
:
join -1 1 -2 2 -a1 -e "0" -o 1.1 2.1 <(sort file1) \
<(cut -d' ' -f1 file2 | sort | uniq -c)
基本上,它将名称file1
与uniq
ue 名称连接起来,并根据file2
使用0
中缺少的字段进行计数file2
。
我awk
会运行:
awk 'NR==FNR{s[$1]++;next}
{if ($1 in s) {print $1, s[$1]}
else {print $1, 0}}' file2 file1
首先读取file2
,计算每个名称出现的次数,然后读取file1
并为每个名称打印计数file2
(如果名称不在其中,则file2
打印 0)。