我有一张包含多个列的表格。第一列是时间,即用户登录的时间;第二列是用户名。
13:15:39 fxs1cia1qulm1lk
13:15:39 fxs1cia1qulm1lk
13:15:39 fxs1cia1qulm1lk
13:15:42 faaaa2aa11111
13:15:49 terd1sfsd11fsdf
13:15:49 terd1sfsd11fsdf
13:15:49 terd1sfsd11fsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:19:19 fxs1ce1iulmla
13:19:19 fxs1ce1iulmla
13:19:19 fxs1ce1iulmla
13:20:42 faaa2a0a1111
那么,我应该怎么做呢?我应该对这两列进行唯一性迭代,如果用户登录的时间和用户名相同,我应该说该用户登录了 3 次以上。我写了一段简短的脚本:
log_file=/root/log
temp_file=/root/temp
temp_file2=/root/temp2
cat /dev/null > $temp_file
cat /dev/null > $temp_file2
cat /dev/null > $result_file
cat $log_file | awk '{print $1}' | tail -n 20 > $temp_file
cat $log_file | awk '{print $5}' | tail -n 20 > $temp_file2
for i in `uniq -c $temp_file | awk '{print $1}'`; do
for y in `uniq -c $temp_file2 | awk '{print $2}'`; do
if [ $i -gt 3 ] && [ $y -gt 3 ]; then
s=`uniq -c $temp_file2 | awk '$1 == '$i`
echo "The user $s has logged more than 3 times"
fi
done
done
请检查一下,您认为这个脚本是否正确?因为,在 echo 中输出我的脚本后,我有:
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
但我想要的是如下输出:
The user 4 21erdsf123sdfsdf has logged more than 3 times
The user 4 abcasbbabadab has logged more than 3 times
就这些。我哪里错了?请帮忙。
答案1
你可以用非常简单的方式做到这一点awk
awk '{ users[$2]++ }
END {
for (user in users)
if (users[user] > 1)
printf "%s logged in %d times\n", user, users[user]
}' < /root.log
该程序扫描 root.log 创建一个包含每个用户计数的关联数组(又名哈希),然后打印大于一的数组。
答案2
那么,唯一的问题是它多次打印相同的输出?为什么不直接通过 uniq 管道?转储到另一个临时文件,然后在其上运行 uniq?
如果这不是你想问的,我有一些观察:
- 在 bash/sh 中处理行分隔数据通常麻烦多多。除非解决方案显而易见,否则请使用一种您不必一直摆弄 IFS 的脚本语言。(如果您不知道 IFS 变量是什么,那么我真的建议不要使用 bash/sh 来处理行分隔数据。)
- 由于您已经在使用 awk,我敢打赌您可以将整个事情作为 awk 脚本来完成。
- 由于您所关注的行是相同的,因此您可以执行
sort logfile | uniq -c
。 - 您没有在 uniq 之前对文件进行排序,因此如果相同的行不相邻,uniq 将不起作用。例如,如果 bob 和 joe 同时登录,并且他们的日志条目交替出现。
- 总是有 grep -c
- 阅读排序命令,特别是 -d、-n、-k 和 -t
更新
您是在寻求有关 shell 脚本的建议,还是在为如何找出当前登录了 3 个或更多会话的人这个问题寻找一个实用的答案?
脚本建议:
- 我确信
$s
包含整个字符串,4 21erdsf123sdfsdf <newline> 4 abcasbbabadab
包括换行符。我不太明白为什么。 - 你为什么这样做
awk '{print $5}'
?我尝试复制您的示例数据并运行它awk '{print $5}'
,结果只得到了一堆换行符,没有其他内容。 - 您是否已查看过其内容
$temp_file
以$temp_file2
确保它们符合您的预期? - 这
tail -n 20
告诉我你只想要“最近”的条目,而你并不关心有多近。这是真的吗? - 这些
cat /dev/null > $file
线是多余的,直接去掉就行。 - 替换
cat $logfile
为sort $logfile
- 缩进循环
基本上,这个脚本不会按照你的要求运行,我也不知道你希望它如何工作,所以我无法提供更具体的建议。抱歉。
实际的
- 使用@greg-tarsa 的 awk 脚本(对不起,Greg,我不知道链接中的用户是否在名字中有一个空格)
- 您是在谈论当前登录到 unix 框的情况吗?您尝试过该
who
命令吗?例如,who | awk '{ print $1}' | sort | uniq -c | sort -d -r
还是该last
命令? - 搜索您总体问题的答案(如何找出谁登录了/登录了太多次),而不是阻碍您已尝试实施的解决方案的更具体的问题(使用两个条件通过两列进行 Uniq)。如果您对练习 shell 脚本更感兴趣,请以这样的方式提问。