我有一个名为 session.log 的文件,它包含一些文本数据。第一列包含序列号。第二列包含用户名。第三列包含上次登录日期。第 4 列包含结果。
一位用户多次登录。我需要找到每个唯一用户的最后登录日期。所以我写了一个shell脚本。输出将显示每个唯一用户(第 2 列)的最新登录日期(第 3 列)的行。输出不应包含多次相同的用户名。
$猫会话.log 1 u1 2018-05-19 通行证 2 u2 2018-06-15 通过 3 u3 2018-05-18 通过 4 u4 2018-05-17 通过 5 u2 2018-05-14 通过 6 u4 2018-07-11 通过 7 u1 2018-05-16 通过 8 u3 2018-05-13 通过 9 u1 2018-08-12 通过 10 u1 2018-05-10 通过
我尝试了什么:
( awk {print} session.log | cut -f2 -d' ' | sort | uniq ) > store.txt
for line in $(cat "store.txt")
do
touch "$line.txt"
grep "$line" session.log > "$line.txt"
temp=$(sort -k3 "$line.txt" | awk 'END{print}')
echo $temp > "$line.txt"
cat "$line.txt"
done
输出
$ ./sort.sh 9 u1 2018-08-12 通过 2 u2 2018-06-15 通过 3 u3 2018-05-18 通过 6 u4 2018-07-11 通过
shell 脚本适用于日期格式 (yyyy-mm-dd) 和 (yyyy/mm/dd)。有没有更好的代码来做同样的工作?使用awk
我们如何做到这一点?
编辑:
$ cat sort.sh
( awk {print} session.log | cut -f2 -d' ' | sort | uniq ) > store.txt
for line in $(cat "store.txt")
do
#touch "$line.txt"
grep "$line" session.log > "$line.txt"
echo $(sort -k3 "$line.txt" | awk 'END{print}')
#temp=$(sort -k3 "$line.txt" | awk 'END{print}')
#echo $temp > "$line.txt"
#cat "$line.txt"
done
rm -f store.txt
(
{ print }
可以完全删除,我只是将其包括在内以显示发生了什么。默认操作是在条件为真时打印整个输入记录。)这将通过减少日期(最近的日期在前)对您拥有的文件进行排序。程序读取排序后的
awk
数据并打印出为每个用户找到的第一个条目。该seen
变量是使用用户名作为键的关联数组/散列。如果用户的值为零,则该用户尚未被看到,因此文件中的行被打印。您的代码与我的注释:
因此,基于您的 shell 循环的替代方法:
同样,
{ print }
可能会从awk
上面的脚本中省略。这仍然为每个用户对会话日志的子集进行一次排序,这有点浪费。
按递减日期对日志进行预排序:
这仍然需要我们从顶部为每个用户扫描一次日志。自然的改进是允许
awk
跟踪哪些用户已经被看到和哪些用户没有被看到,这在顶部给出了我的答案。