Linux 使用Shell脚本提取日志文件中具有自己时间戳的不可预测数据

Linux 使用Shell脚本提取日志文件中具有自己时间戳的不可预测数据,linux,bash,shell,logfile,logfile-analysis,Linux,Bash,Shell,Logfile,Logfile Analysis,log.txt如下所示,这些ID数据具有自己的时间戳(检测时间),将在此log.txt文件中持续更新。ID数据将是不可预测的数字。它可以是0000-9999,并且相同的ID可以再次出现在log.txt中 我的目标是使用shell脚本在首次出现后15秒内过滤再次出现在log.txt中的ID。有人能帮我吗 ID = 4231 detection_time = 1595556730 ID = 3661 detection_time = 1595556731 ID = 2654 detection_t

log.txt
如下所示,这些ID数据具有自己的时间戳(检测时间),将在此log.txt文件中持续更新。ID数据将是不可预测的数字。它可以是0000-9999,并且相同的ID可以再次出现在log.txt中

我的目标是使用shell脚本在首次出现后15秒内过滤再次出现在
log.txt
中的ID。有人能帮我吗

ID = 4231
detection_time = 1595556730 
ID = 3661
detection_time = 1595556731
ID = 2654
detection_time = 1595556732
ID = 3661
detection_time = 1595556733
更清楚地说,从上面的
log.txt
中,ID 3661首先出现在时间1595556731,然后在第一次出现后2秒的时间1595556733再次出现。因此,它与我的条件相匹配,即希望ID在15秒内再次出现。我想通过我的shell脚本筛选这个ID 3661

运行shell脚本后的输出将是
ID=3661

我的问题是我不知道如何用shell脚本开发编程算法

下面是我使用
ID\u new
ID\u previous
变量尝试的内容,但是
ID\u previous=$(ID\u new)detection\u previous=$(detection\u new)
不起作用

input="/tmp/log.txt"
ID_previous=""
detection_previous=""
while IFS= read -r line
do
    ID_new=$(echo "$line" | grep "ID =" | awk -F " " '{print $3}')
    echo $ID_new
    detection_new=$(echo "$line" | grep "detection_time =" | awk -F " " '{print $3}')
    echo $detection_new
    ID_previous=$(ID_new)
    detection_previous=$(detection_new)
done < "$input"
我试过Awk解决方案。结果是
4231
3661
2654
3852
4231
这是log.txt中的所有ID 正确的输出应该是
4231
3661


因此,我认为年龄和身高数据可能会影响Awk解决方案,因为它插入到ID和检测时间这两个重点数据之间。

假设日志文件中的时间戳是单调增加的,您只需要使用Awk进行一次传递。对于每个
id
,跟踪报告的最新时间(使用关联数组
t
,其中键为
id
,值为最新时间戳)。如果您再次看到相同的
id
,并且时间戳之间的差异小于15,请报告它

为了更好地测量,保留我们已经报告的第二个数组
p
,这样我们就不会报告两次

awk'/^ID=/{ID=$3;next}
#如果此行既不是ID也不是检测时间,则跳过
!/^检测时间=/{next}
(id in t)及(t[id]>=$3-15)及!!(p[id]){print id;++p[id];next}
{t[id]=$3}'/tmp/log.txt
如果您真的坚持在Bash中以本机方式执行此操作,我将重构您的尝试以

declare-打印的数据时间
读取时-r字段uu值
做
案例$field in
ID)ID=$value;;
检测时间(分钟)
如果[[dtime[“$id”]-ge$((值-15))];然后
[[-v打印[“$id”]| | echo“$id”
打印[“$id”]=1
fi
dtime[“$id”]=$value;;
以撒
完成
请注意,
read-r
可以像Awk一样轻松地在空白处拆分一行,只要您知道可以预期的字段数。但是
while read-r
通常比Awk慢一个数量级,您必须同意,Awk的尝试更简洁、优雅,并且可以移植到较旧的系统

(bash4中引入了关联数组。)

切向上,任何看起来像
grep'x'|awk'{y}'
的东西都可以重构为
awk'/x/{y}'
;另见

另外,请注意,
$(foo)
尝试将
foo
作为命令运行。为了简单地引用变量
foo
的值,语法是
$foo
(或者,可选地,
${foo}
,但大括号在这里不添加值)。通常,您会希望对扩展名“$foo”
”进行双引号引用;另见

您的脚本只会记住一个较早的事件;关联数组允许我们记住以前看到的所有
ID
值(直到内存耗尽)


也没有什么能阻止我们在Awk中使用人类可读的变量名;您可以随意用
printed
替换
p
,用
dtime
替换
t
来与Bash替代方案完全对等。

这看起来像是一个相当普遍的编程问题。从你的问题来看,我不清楚你是否在开发算法方面有问题,或者是否用你选择的语言实现算法。你最近的修饰性编辑未能解决任何研究工作的明显遗漏。你在找什么?你找到了什么?你尝试了什么,又是怎么失败的?你被困在哪里?您是否理解并满意例如一个微不足道的Awk解决方案?对此表示抱歉。我尽力解释这方面的输出/输入是什么。我是这个linux外壳的新手,而且周围没有人能帮我,所以我只能在这个网站上问这是输出;我的情况是希望ID在15秒内再次出现。我想用我的shell脚本过滤这个ID3661谢谢你的回答。这听起来可能很有趣,但我应该把你的Awk代码放在我的脚本中的什么地方。这将替换整个脚本。谢谢你的解释,这对我帮助很大。我遇到错误
第10行:第15行附近的语法错误]
和第10行:`if[[dtime[“$id”]>=$((value-15))];然后,`。尝试更改语法,但仍然无效。感谢您的反馈;我修复了一个语法错误。但是真正使用Awk脚本来代替;我添加Bash版本只是为了指出您尝试中的错误,并向您大致展示它比普通的Awk脚本复杂多少。我得到的结果是,
log.txt
中的所有ID都被打印出来了,也许过滤时间戳之间的差异小于15秒的ID的条件不起作用?
ID = 4231
detection_time = 1595556730 
Age = 25
Height = 182
ID = 3661
detection_time = 1595556731
Age = 24
Height = 182
ID = 2654
detection_time = 1595556732
Age = 22
Height = 184    
ID = 3661
detection_time = 1595556733
Age = 27
Height = 175
ID = 3852
detection_time = 1595556734
Age = 26
Height = 156
ID = 4231
detection_time = 1595556735 
Age = 24
Height = 184