You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

正则表达式在终端与在线验证工具行为差异及日志提取适配问题

Envoy日志提取UPSTREAM_HOST的Shell正则问题

问题描述

我编写了一个正则表达式用于从模板化的Envoy日志字符串中提取值,该正则在regexr.com等在线验证工具中运行正常,但在Shell环境中执行时出现异常。

日志示例

[2022-11-11T12:07:00.789Z] "GET /check?subject=johnbegucci HTTP/1.1" 200 - "-" 0 17 3 2 "-" "-" "4e4c4fb1-a4d8-4075-8e42-b5fb9216f863" "laundry.transaction.svc.cluster.local:4466" "172.16.107.246:4466" outbound|4466||laundry.transaction.svc.cluster.local 172.16.67.246:51630 10.100.111.246:4466 172.16.67.246:48610 - default
[2022-11-11T13:31:41.189Z] "GET /v1/campaign/198237-jsd-1231 HTTP/1.1" 200 - "-" 0 674 63 63 "-" "Apache-HttpClient/4.5.10 (Java/11.0.7)" "9b3afd5b-c092-4e84-9f29-6380b7f2cafc" "mkt-extractor.mkt-extractor" "172.16.108.138:80" outbound|80||mkt-extractor.mkt-extractor.svc.cluster.local 172.16.65.24:57134 10.100.19.249:80 172.16.65.24:38816 - default

日志格式模板

[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME%\n

现有正则与问题

我编写的正则用于提取UPSTREAM_HOST的值(如outbound|4466||laundry.transaction.svc.cluster.local):

(\[.*\])\s(\".*\")\s([0-9]*)\s(.*)\s(\".*\")\s([0-9]*)\s([0-9]*)\s([0-9]*)\s([0-9]*)\s(\".*\")\s(\".*\")\s(\".*\")\s(\".*\")\s(\".*\")\s(.*)\s(.*)\s(.*)\s(.*)\s(.*)\s(.*)+

在regexr.com上测试时,该正则能正确将两行日志的UPSTREAM_HOST匹配为第14组,但使用awk -v FPAT执行时分组结果异常。提取UPSTREAM_HOST时不同日志需用不同print位置,不利于自动化处理,请问如何用同一print位置处理所有此类日志?

解决方案

方法1:用awk的FPAT正确分割字段

Envoy日志存在带空格的引号字段,直接按空格分割会错位。用FPAT定义字段规则,优先匹配引号包裹的内容,再匹配无空格的连续字符,确保每个字段分割准确:

awk -v FPAT='("[^"]+"|[^[:space:]]+)' '{print $14}' 你的日志文件名

这样UPSTREAM_HOST固定是第14个字段,无论日志内容如何变化,直接print $14即可提取。

方法2:用sed精准捕获目标字段

通过匹配UPSTREAM_HOST之前的所有固定格式内容,捕获目标字段并输出:

sed -E 's/^(\[[^]]+\] "[^"]+" [0-9]+ [^ ]+ "[^"]+" [0-9]+ [0-9]+ [0-9]+ [0-9]+ "[^"]+" "[^"]+" "[^"]+" "[^"]+" "[^"]+") ([^ ]+) .*/\2/' 你的日志文件名

该命令将整个行替换为捕获到的UPSTREAM_HOST值,直接输出结果。

方法3:用grep的PCRE模式提取

如果你的grep支持-P参数(PCRE正则),可以用正向预查定位目标字段:

grep -Po '(?<=^\[[^]]+\] "[^"]+" [0-9]+ [^ ]+ "[^"]+" [0-9]+ [0-9]+ [0-9]+ [0-9]+ "[^"]+" "[^"]+" "[^"]+" "[^"]+" "[^"]+" )[^ ]+' 你的日志文件名

正向预查匹配UPSTREAM_HOST前的所有内容,然后提取后续的非空格字符(即目标值)。

内容的提问来源于stack exchange,提问作者placplacboom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:30:47