首页 > 解决方案 > 使用正则表达式组的 GREP

问题描述

我正在尝试解析一些 apache access.log 并获取用户代理。一条线看起来像

54.183.192.175 - - [27/Nov/2015:16:52:37 +0000] "GET / HTTP/1.0" 200 329 "-" "Mozilla/5.0 (Windows NT 6.3; rv:36.0 Gecko/20100101 Firefox/36.0"

我去了 reg101 站点,最终得到 .*".*".*".*"(.*)" 了站点中与用户代理完美匹配的表达式。然后我尝试在 grep 命令中使用该正则表达式,它根本不返回任何内容。

我尝试使用单引号并将双引号转义但没有成功。有人可以指出我该怎么做?

grep -o '.*".*".*".*"(.*)"' access.log   -- no results at all

grep -o .*\".*\".*\".*\"(.*)\" access.log   -- error `bash: syntax

意外令牌附近的错误('

标签: regexgrep

解决方案


(您使用和)在您的 POSIX BRE 模式中定义了文字括号。

您可以使用以下任一方法提取所需的子字符串

grep -oP '.*"\K[^"]+' file
sed -n 's/.*"\(.*\)".*/\1/p' file
# => Mozilla/5.0 (Windows NT 6.3; rv:36.0 Gecko/20100101 Firefox/36.0

grep -oP '.*"\K[^"]+' file中,由于-P选项而使用了 PCRE 正则表达式引擎。模式匹配到最后一个",省略匹配(就像\KPCRE 运算符一样,丢弃到目前为止匹配的所有文本),然后"在匹配值中匹配一个或多个字符而不是土地。使用-o选项时,匹配是返回值。

sed -n 's/.*"\(.*\)".*/\1/p'中,正则表达式匹配所有直到最后一次出现的",任何零个或多个字符(捕获到组 1),"然后是字符串的其余部分,匹配被替换为组 1 的内容。这就是返回的内容因为-n禁止默认行输出并p打印替换结果。


推荐阅读