我正在编写用于从网络设备解析日志文件的脚本。从设备生成的日志文件不是常规的,这些行不遵循逻辑顺序并且具有多个模式。我的脚本需要从日志行中仅提取与特定模式匹配的日志行,并从该行中提取特定信息作为日期时间,条目类型,资源类型和字符串中url的资源名称。我需要匹配它的模式如下:
dd-mm-yyyy hh:mm:ss INFO spx.resource.media - 新资源' URI' [flags](dlc / tcd)
其中' INFO'是条目类型,' spx.resource.media'资源类型和URI中的资源名称。目前,我们需要过滤具有特定扩展名的那些。
我查看了几篇涉及此主题并在线使用tool的帖子:我带来了这个常规表达:
/(\d{2}-\d{2}-\d{4}\s{1}\d{2}:\d{2}:\d{2})\s{1,}(\w{4})\s{1,}(spx.resource.media)(.{1,}(?<=(?:.jpg)|(?:.png)))/g
问题是最后一个正则表达式组匹配整个URI加上资源类型中的字符和空格,并且y只需要带扩展名的文件名。我试过这个&#39; regex-to-get-a-filename-from-a-url&#39; (不能发布链接信誉不足),但没有锻炼,导致调试器将^ /作为未转义的分隔符。如果删除也不起作用。可以找到日志的一部分here。我真的需要这个。
感谢您阅读和/或回答
答案 0 :(得分:1)
看看这个。首先确定文件的位置,然后您可以相应地循环以获得您想要的内容
<?php
$handle = @fopen("/tmp/inputfile.txt", "r");
if ($handle) {
while (($buffer = fgets($handle, 4096)) !== false) {
echo $buffer;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
?>
答案 1 :(得分:0)
一个月前,有一个解决方案。我想要的是用一种模式提取文件名和其余的子组,我不知道这是否可行,但目前的正则表达式技能不是。所以我所做的就是使用三个正则表达式模式,如下面的代码所示:
这段代码是我(显然)称为Parser的类的一部分。首先,我将模式定义为类中的常量。
/**
* @const string Log line pattern
*/
const LINE_REGEX_PATTERN = '/(\d{2}-\d{2}-\d{4}\s{1}\d{2}:\d{2}:\d{2})\s{1,}(\w{4})\s{1,}(spx.resource.media)(.{1,}(?<=%extensions%))/';
/**
* @const string Full URL pattern
*/
const FULL_URL_PATTERN = '/\b((?:https?|ftps?|file|spx):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$])/i';
/**
* @const string Filename pattern
*/
const RESOURCE_REGEX_PATTERN = '/((?:[^\/][\d\w\.-]+)(?<=%extensions%))/';
如您所见,我使用占位符作为文件扩展名,因为在这种情况下,我需要通过配置或数据库查询动态设置它们。接下来,我针对第一个模式验证每个提取的行
/**
* Line extract
*
* @param string $file_line File line string
*
* @return array An array if matches
* Array (
* [0] => Matched line
* [1] => Date\Time subgroup (format >> d-M-y H:i:s)
* [2] => String flag subgroup
* [3] => Resource type subgroup (not used)
* [4] => Text string containing resource URL
* )
* , null otherwise
*
* @throws RegexException If malformed pattern
*/
private function extractMatches($file_line)
{
$extensions = array();
// build valid extensions subgroup
foreach ($this->valid_extensions as $extension) {
$extensions[] = sprintf("(?:\.%s)", $extension);
}
$matches = array();
// replace extensions placeholder
$pattern = str_replace('%extensions%', implode('|', $extensions), self::LINE_REGEX_PATTERN);
$is_valid = preg_match($pattern, $file_line, $matches);
if ($is_valid === false) {
throw new RegexException();
}
return $matches;
}
从结果数组(如果有的话)中我获取第5个元素(存储带有URL的文本的元素),然后我传递给另外两个函数,第一个是完全URL提取,第二个是最后提取文件名。见下文:
/**
* Full URL extract
*
* @param string $text Text with URL in it
*
* @return string The URL, empty string otherwise
*
* @throws RegexException If malformed pattern
*/
private function extractUrl($text)
{
$match = array();
$is_valid = preg_match(self::FULL_URL_PATTERN, $text, $match);
if ($is_valid === false) {
throw new RegexException();
} elseif ($is_valid === 1) {
return $match[0];
}
return ''; // No URL found!
}
/**
* Filename extract
*
* @param string $url Resource URL (expects no GET parameters)
*
* @return string Resource filename (includes extension), empty string otherwise
*
* @throws RegexException If malformed pattern
*/
private function extractResourceNameFromUrl($url)
{
$extensions = array();
// build valid extensions subgroup
foreach ($this->valid_extensions as $extension) {
$extensions[] = sprintf("(?:\.%s)", $extension);
}
$matches = array();
// replace extensions placeholder
$pattern = str_replace('%extensions%', implode('|', $extensions), self::RESOURCE_REGEX_PATTERN);
$is_valid = preg_match($pattern, $url, $matches);
if ($is_valid === false) {
throw new RegexException();
} elseif ($is_valid === 1) {
return $matches[1];
}
return '';
}
最后我在我的应用程序中的一些地方:
$parser = new Parser();
// fetch file line loop
$matches = $parser->extractMatches($file_line);
$url = $parser->extractUrl($matches[4]);
$filename = $parser->extractResourceNameFromUrl($matches[4]);
希望帮助某人。谢谢!