regex - SED 和 GREP 显示不同的结果

标签 regex sed grep

我试图从我的 Apache 日志中获取特定时间范围内的请求数量。我虽然用 sed 做这件事很容易但是当我尝试对 grep 做同样的事情时我意识到 grep显示的结果多于 sed .

这是grep我使用的命令:

#grep '26/Apr/2017:08:0[0-2]:[0-2][0-4]' access.log 

10.51.32.104 - - [26/Apr/2017:08:00:21 +0100] "GET / HTTP/1.1" 301 762 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"
10.51.32.104 - - [26/Apr/2017:08:00:22 +0100] "GET /index.php?action=Login&module=Users HTTP/1.1" 200 6591 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"
172.30.180.113 - - [26/Apr/2017:08:02:04 +0100] "GET / HTTP/1.0" 301 1906 "-" "Mozilla/4.0 (compatible; ipMonitor 10.7)"
172.30.180.113 - - [26/Apr/2017:08:02:04 +0100] "GET /index.php?action=Login&module=Users HTTP/1.0" 200 21951 "-" "Mozilla/4.0 (compatible; ipMonitor 10.7)"

这是sed命令:
#sed -n '/26\/Apr\/2017:08:00:21/ , /26\/Apr\/2017:08:02:04/p' access.log

10.51.32.104 - - [26/Apr/2017:08:00:21 +0100] "GET / HTTP/1.1" 301 762 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"
10.51.32.104 - - [26/Apr/2017:08:00:22 +0100] "GET /index.php?action=Login&module=Users HTTP/1.1" 200 6591 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"
172.30.180.113 - - [26/Apr/2017:08:02:04 +0100] "GET / HTTP/1.0" 301 1906 "-" "Mozilla/4.0 (compatible; ipMonitor 10.7)"

因此,如您所见,它缺少一个来自 172.30.180.113 的与该模式匹配的访问权限。

我做错了什么?在 sed 中会有任何其他参数有帮助,还是有更好的方法来做到这一点?

最佳答案

您已经非常接近使用 sed 解决它了.这是一个好的开始,我会鼓励你走这条路。

当然你可以用 regex但它有其局限性。考虑范围 08:0009:59 ,正则表达式会很容易 0[89]:[0-5][09] .但如果范围是 08:4509:30 ,然后 regex不会是你的 friend 。因此,我鼓励您在尝试时使用该范围。

您在 sed 中看到的限制是满足结束范围和sed已停止从那里处理。但是我们知道会有更多的线路落在结束范围内。

sed -n '/26\/Apr\/2017:08:00:21/,/26\/Apr\/2017:08:02:04/{p;b};/26\/Apr\/2017:08:02:04/p' access.log

分解 sed 命令:
/26\/Apr\/2017:08:00:21/,/26\/Apr\/2017:08:02:04/{p;b}
这将 p如果在范围内,则打印该行然后 b牧场到尽头sed命令。
/26\/Apr\/2017:08:02:04/p
仅当超出前一个 sed 的范围时才会执行此操作命令。这将处理落入范围内但未被 sed 考虑在范围内的额外行。 .

相同的技术可以用于 awk .
awk '/26\/Apr\/2017:08:00:21/,/26\/Apr\/2017:08:02:04/{a=NR;print};a!=NR && /26\/Apr\/2017:08:02:04/{print}' access.log

第一条命令:
/26\/Apr\/2017:08:00:21/,/26\/Apr\/2017:08:02:04/{a=NR;print}

将打印范围内的行并设置变量 aNR 的值(当前记录号)。

第二条命令:
a!=NR && /26\/Apr\/2017:08:02:04/{print}

将打印范围内的剩余行,但 awk认为超出范围。

关于regex - SED 和 GREP 显示不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43663380/

相关文章:

java - 如何在文本中找到复合字符串

c# - 加拿大邮政编码验证

sed - 查找并替换为相同的通配符

bash - 更改日期字符串格式

linux - 使用 shell 脚本从 unix 中的文件名中提取日期

json - Linux CLI - 如何从 JSON jq + grep 获取子字符串?

java - 正则表达式在 csv 的引用元素中查找逗号

ruby - 包含字符串的第一行(仅)的正则表达式

linux - 如何在bash中将每行的第一个字母大写?

linux - Grep 并增加值