如何用正则表达式从日志字符串中提取用户名与消息?
提取日志中的用户名和消息内容
嘿,既然你已经搞定了日期的提取,那咱们直接把正则整合一下,一次性把日期、用户名和消息都抓出来,效率更高~
首先分析你的日志格式:每条日志都是[日期时间] 用户名: 消息内容的结构,消息里可能包含空格、表情符号,直到下一条日志的[开头或者字符串结束。
完整正则表达式
咱们用一个正则就能捕获所有需要的内容:
/\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] ([^:]+): (.*?)(?=\s*\[|$)/
正则各部分解释
\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]:匹配带方括号的完整日期时间,把时间部分捕获到第1组(和你之前的提取逻辑一致)([^:]+):匹配用户名——因为用户名后面紧跟冒号,所以用[^:]+匹配所有不是冒号的字符,捕获到第2组(如果用户名里可能有冒号,那得调整,但你的示例里没有,这个逻辑完全够用): (.*?)(?=\s*\[|$):匹配冒号+空格后的消息内容:.*?是非贪婪匹配,避免把后面的日志内容也包含进来(?=\s*\[|$)是正向预查,告诉正则“匹配到下一个[(前面可能有空格)或者字符串结尾就停止”,完美分割每条消息
PHP代码示例
因为你的日志是多条连在一起的,用preg_match_all可以一次性提取所有条目:
$log = "[2017-03-14 11:48:22] Steve T: Hi! [2017-03-14 11:49:01] Oscar: Hi! :D How are u doin? [2017-03-14 11:50:24] Steve T: Im doing great :P"; // 用PREG_SET_ORDER让每个日志条目单独成一个数组,方便遍历 preg_match_all('/\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] ([^:]+): (.*?)(?=\s*\[|$)/', $log, $matches, PREG_SET_ORDER); // 遍历输出结果 foreach ($matches as $entry) { $datetime = $entry[1]; $username = trim($entry[2]); // 去掉用户名可能带的前后空格 $message = $entry[3]; echo "时间:{$datetime}\n用户名:{$username}\n消息:{$message}\n\n"; }
运行这段代码后,输出会是:
时间:2017-03-14 11:48:22 用户名:Steve T 消息:Hi! 时间:2017-03-14 11:49:01 用户名:Oscar 消息:Hi! :D How are u doin? 时间:2017-03-14 11:50:24 用户名:Steve T 消息:Im doing great :P
如果只是想单独提取用户名和消息(不需要日期),也可以把正则简化成:
/\[.*?\] ([^:]+): (.*?)(?=\s*\[|$)/
这样第1组是用户名,第2组是消息内容。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

