【问题标题】:Search and Replace Files in Directory搜索和替换目录中的文件
【发布时间】:2016-06-09 14:54:51
【问题描述】:
<span class="itemopener">82 top</span>&nbsp;<span class="allopener">all</span>

我怎样才能将上面的更改为:

<span class="itemopener">top</span>&nbsp;<span class="allopener">82</span>

在一个包含大约 30 个 HTML sn-ps 的 html 文件上使用 PHP。

注意:82 可以是大于 1 的任意整数。

另外,我想从我放置在一个目录中的一个新文件中运行这个脚本,该文件将为该目录中的每个 8000 个 HTML 文件运行一次搜索和替换(脚本在完成之前不能超时 -也许是一些反馈。)

【问题讨论】:

  • 让我们看看我是否理解:你想要一个脚本读取 8000 个 HTML 文件,并在每个文件中搜索一行并替换为另一行,对吗?
  • 1 个目录。 8000 个 htm 文件。每个文件都有一大块文本,其中大约有 30 个目标 sn-ps 需要更改。所以大约 8000 * 30 次替换。
  • 这是一个示例页面:hackerbra.in/unlisted/best_1360386661.htm

标签: php regex server directory preg-replace


【解决方案1】:

我写了替换行的函数:

 function replace($row){
    $replaced = preg_replace_callback("~(\<span class=\"itemopener\"\>)(\d{1,5})\s(top\</span\>.*\<span class=\"allopener\"\>).{3}(\</span\>)~iU", function($matches){
    $str = $matches[1] . $matches[3] . $matches[2] . $matches[4];
    return $str;
    }, $row);
    return $replaced;
 }

$s = '<span class="itemopener">82 top</span>&nbsp;<span class="allopener">all</span>';
$replaced = replace($s);

echo "<pre>" . print_r($replaced, 1) . "</pre>";
exit();

Working demo of the function

如果您将文件按一行,并做一些简单的检查是否有您要替换的那些跨度,那么您可以将它们发送到这个函数中.. 但是对于您指定的文件数量,这将需要一些时间。

要扫描路径中的所有文件,您可以在此处使用我的答案:scandir 稍加编辑后,您可以将其修改为只读 .htm 文件,并返回您想要的结构..

然后,您获取所有扫描的 htm 文件并使用以下方式处理它们:

$allScannedFiles = array("......");
foreach($allScannedFiles as $key => $path){
    $file = file_get_contents($path);
    $lines = explode(PHP_EOL, $file);
    $modifiedFile = "";
    foreach($lines as $line){
        if(strpos($line, "span") && strpos($line, "itemopener")){
             $line = replace($line);
        }
        $modifiedFile .= $line . PHP_EOL;
    }
    file_put_contents($path, $modifiedFile);
}

我从头开始写了这个sn-p,所以需要进行一些测试.. 然后运行它,去给自己煮咖啡并等待:) 如果它会超时,你可以增加 php 超时。如何做到这一点在此处询问和回答:how to increase timeout in php

或者,您可以尝试将文件加载为 DOMDocument 并对该类进行替换 documentation of DomDocument 但是如果文件中的某处不是有效的 html,它可能会给你带来问题..

【讨论】:

  • thx .. 这行得通,但确实需要一个完整的答案来运行所有文件以接受,但可能稍后。
  • 编辑了我的答案,所以它包含提示如何做整个事情
【解决方案2】:

我正在使用@Jimmmy 创建的函数(将d{2} 替换为d{1,5},因为“注意:82 可以是大于1 的任何整数”)并添加了文件搜索(经过测试,效果很好):

<?php

function replace($row){
    $replaced = preg_replace_callback("~(\<span class=\"itemopener\"\>)(\d{1,5})\s(top\</span\>.*\<span class=\"allopener\"\>).{3}(\</span\>)~iU", function($matches){
        $str = $matches[1] . $matches[3] . $matches[2] . $matches[4];
        return $str;
    }, $row);
    return $replaced;
}

foreach ( glob( "*.html" ) as $file )         // GET ALL HTML FILES IN DIRECTORY.
{ $lines = file( $file );                     // GET WHOLE FILE AS ARRAY OF STRINGS.
  for ( $i = 0; $i < count( $lines ); $i++ )  // CHECK ALL LINES IN ARRAY.
    $lines[ $i ] = replace( $lines[ $i ] );   // REPLACE PATTERN IF FOUND.
  file_put_contents( $file,$lines );          // SAVE ALL ARRAY IN FILE.
}
?>

【讨论】:

  • 谢谢 Jose.. 只能在几个小时内检查一下.. 抱歉。
猜你喜欢
  • 2022-01-07
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 2015-06-29
相关资源
最近更新 更多