【问题标题】:Match values inside of a block with delimiters PHP regex使用分隔符 PHP regex 匹配块内的值
【发布时间】:2017-02-23 20:38:16
【问题描述】:

我在这里有一个正则表达式问题,我想解析这个日志文件,现在我想获取 SESSION 中的键和值

问题在于日志看起来并不完全相同,其中一些缺少包含“SESSION”的#字符,它们都包含单词 SESSION 来开始变量块,并且它们都以另一个总是包含“POST”或“API CURL CALL”字样的块。

所以我必须使用最有可能使其忽略这些字符串之间的任何内容的量词,但是当匹配这两个其他值中的任何键和值集(由:) 时...

光说这些就满嘴了……我完全被难住了,所以我在这件事上向你们寻求一些指导和帮助。 目标是将这些糟糕的日志解析成我可以快速阅读和理解的内容。

我正在 PHP 中创建一个类来执行此操作并输出一些漂亮的 HTML 格式日志。 这是当前的日志文件。

[05:40:40] ################
[05:40:40] #### SOURCE ####: /zalo/vn/interface.call.php
[05:40:40] #### REQUEST ####: /zalo/vn/interface.call.php
[05:40:40] #### Refer: http://app.com/zalo/vn/?v=1&adsid=d6e5f33e5a94d9fafaf15dc0cf4a1e5&sub_id=170100sf01435487523&sub_id1=232s5
[05:40:40] #### SESSION #####
[05:40:40] v: 1 
[05:40:40] adsid: d6e5f33e5a94d93sfsf5dc0cf4a1e5 
[05:40:40] sub_id: 799e12b08fa1edes1d7bgsg0506a6e9 
[05:40:40] landingpage: http%3A%2F%2Fapp.com%2Fzalo%2Fvn%2Finterface.call.php 
[05:40:40] c_id: da21bae82c02d1e2b8168d57cd3fbab7 
[05:40:40] nId: 3943 
[05:40:40] partner: Marvel
[05:40:40] country_code: 84 
[05:40:40] country: VN 
[05:40:40] url: http://app.com/zalo/vn/ 
[05:40:40] campaign_id: 1066 
[05:40:40] source: web 
[05:40:40] msisdn: 906346534 
[05:40:40] Phone: 906346534 
[05:40:40] #### POST ####
[05:40:40] action: subscribe 
[05:40:40] Phone: 906346534 
[05:40:40] ################
[05:40:40] #### API CURL CALL ####

理想情况下,我想保留此部分

v: 1 
adsid: d6e5f33e5a94d93sfsf5dc0cf4a1e5 
sub_id: 799e12b08fa1edes1d7bgsg0506a6e9 
landingpage: http%3A%2F%2Fapp.com%2Fzalo%2Fvn%2Finterface.call.php 
c_id: da21bae82c02d1e2b8168d57cd3fbab7 
nId: 3943 
partner: Marvel
country_code: 84 
country: VN 
url: http://app.com/zalo/vn/ 
campaign_id: 1066 
source: web 
msisdn: 906346534 
Phone: 906346534 

我可能需要某种后瞻前瞻组合。

(?=SESSION).*?(?<=POST)

类似的东西,但也删除了我不需要的实际 SESSION 和 POST 关键字的时间戳。

【问题讨论】:

  • @michaJlS 我尝试了一些我在网上看到的不同的东西/(?&lt;=#### SESSION #####).*?(?=\[05:40:40\] #### POST ####)/si Lookbehinds 看起来他们可能会工作,但我不能使用 #* 例如,我必须提供一个非常具体的要开始的字符串,这是一个问题,因为即使我知道字符串将包含 SESSION,我也不确切知道它是否以 # 开头,例如单词 SESSION 或 -- SESSION...
  • @michaJlS 我还在问题中提供了一个可能更好的例子。
  • 那么,你已经知道如何匹配这些块了,对吧?为什么不直接删除所有不需要的细节和线条?
  • 您可以尝试 like this demo at eval.in 的正则表达式解释,请参阅 regex101 part 1 to match SESSION partpart 2 to extract key/values
  • @bobblebubble 我不确定你为什么提供了一个有效的答案作为评论。

标签: php regex pcre regex-lookarounds


【解决方案1】:

如果文件不是太大,你可以循环遍历整个文件:

$foo = file("test.txt");
$insession = false;
foreach ($foo as $line) {
    if (!$insession) {
        if (strpos($line, "SESSION") === false) continue;
        $insession = true;
        continue;
    }
    if (strpos($line, "POST") !== false) break;
    if (preg_match("/^\[[\d:]+?\] (.*)$/", $line, $matches)) {
        echo "$matches[1]\n";
    }
}

【讨论】:

  • 逐行读取日志会更节省内存
  • 是的,我假设这是 a) 一个相当小的文件,b) 在 HTTP 请求期间实时发生。如果其中任何一个不正确,则有更好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
相关资源
最近更新 更多