Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 用于文本之间匹配的正则表达式_Php_Regex - Fatal编程技术网

Php 用于文本之间匹配的正则表达式

Php 用于文本之间匹配的正则表达式,php,regex,Php,Regex,我有一个文件,其中包含从apache http日志自动生成的统计数据 我真的很难在两段文字之间匹配行。这是我拥有的统计文件的一部分: jpg 6476 224523785 0 0 Unknown 31200 248731421 0 0 gif 197 408771 0 0 END_FILETYPES # OS ID - Hits BEGIN_OS 12 linuxandroid 1034 winlong 752 winxp 1320 win2008 204250 END_OS # Brows

我有一个文件,其中包含从apache http日志自动生成的统计数据

我真的很难在两段文字之间匹配行。这是我拥有的统计文件的一部分:

jpg 6476 224523785 0 0
Unknown 31200 248731421 0 0
gif 197 408771 0 0
END_FILETYPES

# OS ID - Hits
BEGIN_OS 12
linuxandroid 1034
winlong 752
winxp 1320
win2008 204250
END_OS

# Browser ID - Hits
BEGIN_BROWSER 79
mnuxandroid 1034
winlong 752
winxp 1320
我想做的是编写一个正则表达式,它只在标签
BEGIN\u OS 12
END\u OS
之间搜索

例如,我想创建一个包含操作系统和点击的PHP数组(我知道实际的数组实际上不会完全像这样,但只要我有这些数据):

我已经用gskinner regex tester测试正则表达式好几个小时了,但是regex远远不是我的强项

我想发布我到目前为止得到的内容,但我已经尝试过加载,我得到的最接近的一个是:

^[BEGIN_OS\s12]+([a-zA-Z0-9]+)\s([0-9]+)
这太可怕了


任何帮助都将不胜感激,即使是“无法完成”。

您可以尝试以下方法:

/BEGIN_OS 12\s(?:([\w\d]+)\s([\d]+\s))*END_OS/gm
/BEGIN_OS 12([\s\S]*)END_OS/gm
您仍然需要解析匹配以获得结果,您还可以使用以下方法对其进行简化:

/BEGIN_OS 12\s(?:([\w\d]+)\s([\d]+\s))*END_OS/gm
/BEGIN_OS 12([\s\S]*)END_OS/gm
然后只需解析第一组(它们之间的文本)并在
'\n'
上拆分,然后
'
即可获得所需的部分

编辑

带注释的正则表达式:

/BEGIN_OS 12          // Match "BEGIN_OS 12" exactly
 \s                   // Match a whitespace character after
 (?:                  // Begin a non-capturing group
   ([\w\d]+)          // Match any word or digit character, at least 1 or more
   \s                 // Match a whitespace character
   ([\d]+\s)          // Match a digit character, at least one or more
 )*                   // End non-capturing group, repeate group 0 or more times           
 END_OS               // Match "END_OS" exactly
/gm                   // global search (g) and multiline (m)
简单的版本是:

/BEGIN_OS 12          // Match "BEGIN_OS 12" exactly
  (                   // Begin group
    [\s\S]*           // Match any whitespace/non-whitespace character (works like the '.' but captures newlines
  )                   // End group
  END_OS              // Match "END_OS" exactly
/gm                   // global search (g) and multiline (m)
二次编辑

您的尝试:

^[BEGIN_OS\s12]+([a-zA-Z0-9]+)\s([0-9]+)
不会给你你期望的结果。如果你把它拆开:

^                     // Match the start of a line, without 'm' this means the beginning of the string.
[BEGIN_OS\s12]+       // This means, match a character that is any [B, E, G, I, N, _, O, S, \s, 1, 2] 
                      // where there is at least 1 or more. While this matches "BEGIN_OS 12" 
                      // it also matches any other lines that contains a combination of those 
                      // characters or just a line of whitespace thanks to \s).
([a-zA-Z0-9]+)        // This should match the part you expect, but potentially not with the previous rules in place.
\s
([0-9]+)              // This is the same as [\d]+ or \d+ but should match what you expect (again, potentially not with the first rule)

您可以尝试以下方法:

/BEGIN_OS 12\s(?:([\w\d]+)\s([\d]+\s))*END_OS/gm
/BEGIN_OS 12([\s\S]*)END_OS/gm
您仍然需要解析匹配以获得结果,您还可以使用以下方法对其进行简化:

/BEGIN_OS 12\s(?:([\w\d]+)\s([\d]+\s))*END_OS/gm
/BEGIN_OS 12([\s\S]*)END_OS/gm
然后只需解析第一组(它们之间的文本)并在
'\n'
上拆分,然后
'
即可获得所需的部分

编辑

带注释的正则表达式:

/BEGIN_OS 12          // Match "BEGIN_OS 12" exactly
 \s                   // Match a whitespace character after
 (?:                  // Begin a non-capturing group
   ([\w\d]+)          // Match any word or digit character, at least 1 or more
   \s                 // Match a whitespace character
   ([\d]+\s)          // Match a digit character, at least one or more
 )*                   // End non-capturing group, repeate group 0 or more times           
 END_OS               // Match "END_OS" exactly
/gm                   // global search (g) and multiline (m)
简单的版本是:

/BEGIN_OS 12          // Match "BEGIN_OS 12" exactly
  (                   // Begin group
    [\s\S]*           // Match any whitespace/non-whitespace character (works like the '.' but captures newlines
  )                   // End group
  END_OS              // Match "END_OS" exactly
/gm                   // global search (g) and multiline (m)
二次编辑

您的尝试:

^[BEGIN_OS\s12]+([a-zA-Z0-9]+)\s([0-9]+)
不会给你你期望的结果。如果你把它拆开:

^                     // Match the start of a line, without 'm' this means the beginning of the string.
[BEGIN_OS\s12]+       // This means, match a character that is any [B, E, G, I, N, _, O, S, \s, 1, 2] 
                      // where there is at least 1 or more. While this matches "BEGIN_OS 12" 
                      // it also matches any other lines that contains a combination of those 
                      // characters or just a line of whitespace thanks to \s).
([a-zA-Z0-9]+)        // This should match the part you expect, but potentially not with the previous rules in place.
\s
([0-9]+)              // This is the same as [\d]+ or \d+ but should match what you expect (again, potentially not with the first rule)

正则表达式可能不是此作业的最佳工具。您可以使用正则表达式获取所需的子字符串,然后使用PHP的字符串操作函数进行进一步处理

$string = preg_replace('/^.*BEGIN_OS \d+\s*(.*?)\s*END_OS.*/s', '$1', $text);

foreach (explode(PHP_EOL, $string) as $line) {
    list($key, $value) = explode(' ', $line);
    $result[$key] = $value;
}

print_r($result);
应为您提供以下输出:

Array
(
    [linuxandroid] => 1034
    [winlong] => 752
    [winxp] => 1320
    [win2008] => 204250
)

正则表达式可能不是此作业的最佳工具。您可以使用正则表达式获取所需的子字符串,然后使用PHP的字符串操作函数进行进一步处理

$string = preg_replace('/^.*BEGIN_OS \d+\s*(.*?)\s*END_OS.*/s', '$1', $text);

foreach (explode(PHP_EOL, $string) as $line) {
    list($key, $value) = explode(' ', $line);
    $result[$key] = $value;
}

print_r($result);
应为您提供以下输出:

Array
(
    [linuxandroid] => 1034
    [winlong] => 752
    [winxp] => 1320
    [win2008] => 204250
)

如果没有要匹配的实际模式,但有固定字符串,为什么要使用正则表达式?使用字符串函数获取它们的位置,获取中间的文本…然后首先在新行字符处分解它们,然后在循环中的空格处分解它们,你就在了。我本来会尝试这种方法,但认为可能有点混乱,到处都是字符串拆分数组!我会很快去做的。如果没有实际的模式可以匹配,但有固定的字符串,为什么要使用正则表达式呢?使用字符串函数获取它们的位置,获取中间的文本…然后首先在新行字符处分解它们,然后在循环中的空格处分解它们,你就在了。我本来会尝试这种方法,但认为可能有点混乱,到处都是字符串拆分数组!我会很快尝试一下。谢谢@amal murali,我不确定纯regex是否是最好的方式,但你的答案是完美的,非常感谢:)谢谢@amal murali,我不确定纯regex是否是最好的方式,但你的答案是完美的,非常感谢:)谢谢@izuriel我会投票,因为它很有帮助,而且解释得很好!我发现这些注释非常有用(因为我的正则表达式功能是新手级的!)(一件事是g修饰符在PHP
preg\u match\u all
:()我不经常使用PHP,但有些语言有充当“g”修饰符的方法。在Ruby中,你可以使用
gsub
而不是
sub
来做同样的事情,就像应用了“g”修饰符一样。这在PHP中可能是一样的。我还添加了一些关于你尝试使用正则表达式的内容。@izuriel:在PHP中,等效的是
preg\match_all()
:)谢谢@izuriel我会投票的,因为它很有帮助,而且解释得很好!我发现这些注释非常有用(因为我的正则表达式功能是新手级的!)(一件事是g修饰符在PHP
preg\u match\u all
:()我不经常使用PHP,但有些语言有充当“g”修饰符的方法。在Ruby中,你可以使用
gsub
而不是
sub
来做同样的事情,就像应用了“g”修饰符一样。这在PHP中可能是一样的。我还添加了一些关于你尝试使用正则表达式的内容。@izuriel:在PHP中,等效的是
preg\match_all()
:)