需要一个相当复杂的正则表达式来处理简单的文本文档

时间:2012-04-13 19:05:13

标签: php regex perl

我更喜欢使用php或perl的答案,因为我可以轻松地使用它们

文件格式如下:

Name : ...
INSERT INTO (...) Values (...)
Name : ...                         <--- These are the lines I need
INSERT INTO (...) Values (...)     <--- 
<span style='color:red;'>FAILED to INSERT ...</span>
Name : ...
INSERT INTO (...) Values (...)
...

“FAILED to INSERT”范围后面的行是我感兴趣的行。 我想删除所有成功的插入,只留下Name:和INSERT INTO部分失败的行。

“Name:”和“INSERT INTO ...”部分不一定是一行。

这是我认为我需要匹配的伪模式:

(/Name:/)(any character)(/INSERT INTO/)(anything but not /Name:/)(/FAILED to INSERT/)

哪会留下我

Name: ...
INSERT INTO ...
<span ...> FAILED to INSERT

对于每个失败的插入

我熟悉一些正则表达式的基础知识,但可以对此使用一些帮助。 我怎么能在perl或php中做到这一点?

4 个答案:

答案 0 :(得分:4)

我认为这不是正则表达式的合适任务。阅读文件并逐行累积所需信息更为清晰。

这是一个使用您提供的示例数据的Perl解决方案。

use strict;
use warnings;

my $info;

while (<DATA>) {
  $info = '' if /Name :/;
  $info .= $_;
  print $info if /FAILED to INSERT/;
}

__DATA__

Name : ...
INSERT INTO (...) Values (...)
Name : ...                         <--- These are the lines I need
INSERT INTO (...) Values (...)     <--- 
<span style='color:red;'>FAILED to INSERT ...</span>
Name : ...
INSERT INTO (...) Values (...)
...

<强>输出

Name : ...                         <--- These are the lines I need
INSERT INTO (...) Values (...)     <--- 
<span style='color:red;'>FAILED to INSERT ...</span>

我希望很清楚如何从文件中读取数据。如果在命令行上传递文件名,则只需将循环更改为while (<>) { ... }


修改

对于单行命令解决方案,这个怎么样

perl -0777 -ne"/FAILED to INSERT/ and print for split /(?=Name :)/" myfile

<强>输出

Name : ...                         <--- These are the lines I need
INSERT INTO (...) Values (...)     <---
<span style='color:red;'>FAILED to INSERT ...</span>

答案 1 :(得分:3)

我相信@FritsvanCampen走在正确的轨道上。而不是使用正则表达式,逐行遍历整个文件就好了。这是使用多维数组的略微修改版本。 (仅供参考,我真的不知道php,所以可能需要调整一两次)。

$handle = fopen("strangefile.txt", "r");

$names = array();
$name = array();
while($line = fgets($handle)) {
    if (substr($line, 0, 5) === "Name:") {
      // start a new name array
      $name = array($line);
    }
    else
    {
      // append to existing name array
      $name[] = $line;

      // check to see if the current name array is type 'error'
      if (substr($line, 0, 31) === "<span style='color:red;'>FAILED to INSERT") {
        $names[] = $name;
      }
    }
}
var_dump($names);

答案 2 :(得分:2)

Regexps是一种痛苦,这样的事情怎么样?

$handle = fopen("strangefile.txt", "r");

$collect = true;
$names = array();
while($line = fgets($handle)) {
    if (substr($line, 0, 31) === "<span style='color:red;'>FAILED to INSERT") {
        $collect = false;
    } else if ($collect && substr($line, 0, 5) === "Name:") {
        $names[] = $line;
    }
}
var_dump($names);

答案 3 :(得分:2)

Frits van Campen一样,正则表达式只能是解决方案的一部分,而不是整个解决方案,如果您想快速解决这个问题。我在his answer中使用了一些其他逻辑,因为它不完全正确:

$file = new SPLFileObject("strangefile.txt");

foreach($file as $line)
{
    if (isset($buffer) && substr($line, 0, 25) === "<span style='color:red;'>") {
        echo $buffer . $line;
        unset($buffer);
        continue;
    }

    if (substr($line, 0, 5) === "Name:") {
        $buffer = '';
    }
    isset($buffer) && $buffer .= $line;
}