找到一个关键字,然后显示每一行,直到它在 PHP 中找到下一个关键字

Find a keyword, then display each line until it finds the next keyword in PHP

提问人:codename_zoe 提问时间:10/19/2023 最后编辑:mickmackusacodename_zoe 更新时间:10/20/2023 访问量:91

问:

我想做的是:

  1. 打开 sql 文件
  2. 找到一个关键字,然后显示该行
  3. 继续显示每一行,直到下一个关键字
  4. 继续做 1 - 3,直到文件结束

这是我的代码,但它在第一次匹配后停止显示:

<?php
$filename = 'test.sql';
$startWord = ':begin';
$endWord = 'sqlexception';

// Open the SQL file for reading
$file = fopen($filename, 'r');

if ($file) {
    $foundStart = false;

    while (!feof($file)) {
        $line = fgets($file);

        if ($foundStart || stripos($line, $startWord) !== false) {
            $foundStart = true;
            echo $line; // Display the current line

            if (stripos($line, $endWord) !== false) {
                $foundStart = false; // Stop displaying lines after finding the end word
            }
        }
    }

    fclose($file);
} else {
    echo "Unable to open the file.";
}
?>

这是我想从中检索数据的sql文件

getDataNlp:begin


    declare continue handler for sqlexception 
    begin
        set returnCode = -1;
        set returnMsg = 'SQL Exception';
    end;
    
    if useTransaction = 1 then
        start transaction;
    end if;
    
    set returnMsg = '';
    set returnCode = 0;
    set @count = 0;
    set @orgName = orgName;
    set @orgId = '';
    set @oprEmail = oprEmail;

CreateOpr:BEGIN


    DECLARE idx INT DEFAULT 1;
    DECLARE v_orgName VARCHAR(128) DEFAULT '';
    declare continue handler for sqlexception 
    begin
        set returnCode = -1;
        set returnMsg = 'SQL Exception';
    end;
    start transaction;

    set returnCode = 0;
    set returnMsg = '';
    set @count = 0;
    set @oprName = oprName;
            
    select count(1) into @count from Opr where name = @oprName;
    if (@count > 0) then
        set returnCode = -1;
        set returnMsg = 'Opr with same oprName already exist';
        rollback;
        leave CreateOpr;
    end if;
 
END ;;

我想像这样检索这些行

getDataNlp: begin

    declare continue handler for sqlexception 
php 提取 文本 sql 解析器

评论

3赞 user3783243 10/19/2023
你能提供你正在使用的示例文件吗?逻辑看起来是正确的,3v4l.org/EO7Qn,假设文件有多个对术语的引用
1赞 jarlh 10/19/2023
你怎么知道一个词是否是关键词?
0赞 codename_zoe 10/19/2023
@user3783243 我在问题中添加了示例 sql 数据
0赞 mickmackusa 10/19/2023
请不要在最小的可重现示例中对示例数据进行 yatta-yatta。提供极具挑战性的输入和您确切期望的输出,以便可以一致准确地判断答案。
0赞 codename_zoe 10/19/2023
@mickmackusa 很抱歉缩短了 sql 代码,我添加了一个代码块,希望它能给你一个想法。我只想检索问题中的 2 行,我认为缩短代码不是问题。

答:

0赞 adek- 10/19/2023 #1

代码在第一次匹配后停止显示的原因是,在找到 .由于您正在逐行读取文件,因此变为 false,并且它停止显示任何后续行。$foundStart$endWord$foundStart

检查这个而不是你的:while

while (!feof($file)) {
    $line = fgets($file);

    if (stripos($line, $startWord) !== false) {
        $foundStart = true; 
    }

    if ($foundStart) {
        echo $line . '<br>'; 
    }

    if (stripos($line, $endWord) !== false && $foundStart) {
        echo "---- End of Block ----<br>"; 
        $foundStart = false; 
    }
}

评论

0赞 mickmackusa 10/19/2023
错误:未定义$foundStart。在发布之前,您是否测试了代码?
0赞 codename_zoe 10/19/2023
谢谢,它正在工作,但是是否可以添加类似“如果在接下来的 5 行中找不到$endWord,请跳过并查找$startWord”之类的内容?
0赞 mickmackusa 10/19/2023
请澄清您的问题,以包含足够具有挑战性的输入,以演示已知的麻烦场景,并显示您确切期望的结果@cod
0赞 adek- 10/19/2023
在线 php 编辑器中的@mickmackusa无法在 VSCode 中使用文件完美无缺,如果您因为该资源而贬低我,那么这是不公平的。codename_zoe如果我理解得很好,您想添加一个计数器来跟踪在找到$startWord后和遇到$endWord之前读取的行数。如果计数器达到某个限制,比如 5 行,您希望将$foundStart重置为 false 并继续寻找下一个$startWord?
0赞 codename_zoe 10/19/2023
@adek - 谢谢。我添加了一个计数器,现在它工作正常
1赞 mickmackusa 10/19/2023 #2

我可能只是一口气解析整个 sql 文件,而不是尝试逐行解析。preg_match_all()

使用范围量词来声明找到的开始和结束关键字之间允许的行数。{0,$yourLimit}

A 将匹配所有非垂直空格字符。我假设您不需要多字节支持,但可以添加到模式修饰符中。 不区分大小写。 使匹配项成为行的末尾,而不是字符串的末尾。 匹配换行符序列。我在末尾使用前瞻来 rtrim() 空白,我认为您不希望在结果中出现。.uim$\R

代码:(演示)

$startWord = ':begin';
$endWord = 'sqlexception';
$maxLinesBetween = 4;
preg_match_all('#.*' . preg_quote($startWord) . '.*(?:\R.*){0,' . $maxLinesBetween . '}.*' . preg_quote($endWord) . '.*?(?=\s*$)#im', $sql, $m);
var_export($m[0]);

评论

0赞 user3783243 10/19/2023
嗯,以前没见过/用过。这与 ?\R\v
0赞 codename_zoe 10/19/2023
我尝试了此代码,但它返回以下错误:“已弃用:preg_match_all():已弃用将 null 传递给字符串类型的参数 #2 ($subject) ”
0赞 mickmackusa 10/20/2023
@cod 我有的地方,您将需要访问文件内容()。关于 versus ,将匹配单个垂直线条字符(例如 或 . 匹配新行 seqence -- , , 或 。这是一个很好的 stackoverflow.com/a/63922758/2943403 示范$sqlfile_get_contents()\v\R\v\r\n\R\r\n\r\n\R