Php 对于简单的文本文档,需要一个相当复杂的正则表达式

Php 对于简单的文本文档,需要一个相当复杂的正则表达式,php,regex,perl,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 ...</

我更喜欢用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 (...)
...
这将留给我

Name: ...
INSERT INTO ...
<span ...> FAILED to INSERT
名称:。。。
插入到。。。
插入失败
对于每个失败的插入

我熟悉一些正则表达式的基本知识,但在这方面需要一些帮助。
如何在perl或php中实现这一点?

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);
$handle=fopen(“奇异文件.txt”、“r”);
$collect=true;
$names=array();
而($line=fgets($handle)){
if(substr($line,0,31)=“插入失败”){
$collect=false;
}else if($collect&&substr($line,0,5)=“Name:”){
$names[]=$line;
}
}
var_dump(名称);
就像,如果您想快速解决这个问题,regex只能是解决方案的一部分,而不是整个解决方案。我使用了中的其他逻辑,因为它不完全正确:

$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;
}
$file=new SPLFileObject(“奇异文件.txt”);
foreach($文件作为$行)
{
if(isset($buffer)和substr($line,0,25)==“”){
echo$buffer.$line;
未结算($缓冲);
继续;
}
if(substr($line,0,5)=“Name:”){
$buffer='';
}
isset($buffer)和&$buffer.=$line;
}

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

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

使用严格;
使用警告;
我的$info;
而(){
$info=''如果/Name:/;
$info.=$\uU4;
如果插入/失败,则打印$info;
}
__资料__
姓名:。。。
插入到(…)值(…)

姓名: 我相信@FritsvanCampen走上了正确的道路。与其使用正则表达式,还不如一行一行地遍历整个文件。这是一个使用多维数组的稍加修改的版本。(仅供参考,我并不真正了解php,因此可能需要进行一两次调整)

$handle=fopen(“奇异文件.txt”、“r”);
$names=array();
$name=array();
而($line=fgets($handle)){
if(substr($line,0,5)=“Name:”){
//启动一个新的名称数组
$name=数组($line);
}
其他的
{
//附加到现有名称数组
$name[]=$line;
//检查当前名称数组是否为“error”类型
if(substr($line,0,31)=“插入失败”){
$names[]=$name;
}
}
}
var_dump(名称);

如果我想要的行在错误行之后,那么这将起作用,但是我想要的行在错误行之前。因此,如果我使用逐行解决方案,直到我已经处理了相关的行,我才知道这是一个错误,这就是它所做的。。直到在行首看到
“插入失败”
,它才开始收集。如果有三行,第一行是名称:line,第二行是插入行,第三行是,我需要前两行,在我看到第三行是跨度之后。使用您的方法,$line将是第1行,然后是第2行,第3行上的$start将是true。然后在下一行(第4行)上,它将占用整行逻辑是有点颠倒的,但是基本上它是可以通过这种方式求解的,与类似的方式进行比较。哦,在这种情况下,反转对
$start
的检查,一旦看到表示错误行的行,就停止收集。我已经更新了代码。这似乎更合理,但我不确定我是否完全遵循了。foreach循环逐行拆分文档,对吗?如果我们已经进入下一行,我们如何检索上一行?@pclem12:正确,逐行
$buffer
存储自上一个
名称:
以来的所有行,这就是它的用途。@hakre-+1我有同样的想法,但不太懂php。我喜欢使用$buffer。谢谢,这看起来是一个很好的解决方案,而且更直观。我来试一试
$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;
}
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>
$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);