【问题标题】:PHP Simple Search ExamplePHP 简单搜索示例
【发布时间】:2014-03-22 06:56:40
【问题描述】:

我正在学习 PHP,并在文本文件脚本中构建了一个小搜索。以下是事件链:

  1. 打开文本文件
  2. 从每一行创建数组
  3. 如果提交了表单,则将发布数据放入一个函数中,该函数运行一个正则表达式来查找部分字符串或单词,如果匹配,则所有条目都会在代码中替换为一个类,并带有一些 CSS。

我的问题是:

如果我有这样的句子:

汤姆手里拿着相机。我也是地板上的摄像头。

然后搜索“am”,它会搜索并找到相机,并将其替换为 span 类。然后它找到 "am" 并在 Camera 中替换它两次,并替换它自己。

这是我的代码:

    //---- Puts Array into or responds with error
    $lines = file($filename, FILE_IGNORE_NEW_LINES);
    if ( !is_array($lines) ) {
       echo 'Cannot create array from file';
    }

    //---- Scans and Displays Lines
    $submission = $_GET['Search'];
    function scanLines($lines, $submission) {
        foreach($lines as $line) {      
            if(strpos($line,$submission)!== false){             
                preg_match_all("/\b[a-z]*".preg_quote($submission)."[a-z]*\b/i", $line, $matches);  

                $i = 0;
                foreach($matches[$i] as $match) {   
                    $line = str_replace($match, '<span class="highlight">'.$match.'</span>', $line);
                $i++;                   
            }
            echo $line;
        }       
    }       
}

示例的直接链接:http://www.effectivemark.com/testphp/

我的问题是:过滤掉相机中“am”的最佳方法是什么,所以它不会添加带有 span 标签的字符串,如下所示:

    <span class="highlight">c<span class="highlight">am</span>era</span>

更新代码:

//---- Scans and Displays Lines
$submission = $_GET['Search'];
function scanLines($lines, $submission) {
    foreach($lines as $line) {      
        if(strpos($line,$submission)!== false){ 

            $words = explode(' ', $line);
            $i = 0;
            $combine = array();
            foreach($words as $word) {
                if (preg_match("/\b[a-z]*".preg_quote($submission)."[a-z]*\b/i", $word)) {
                    preg_match_all("/\b[a-z]*".preg_quote($submission)."[a-z]*\b/i", $word, $match);
                    $matches = '<span class="highlight">' . $match[0][0] . '</span>';
                }
                else { 
                    $matches = $word;
                }
                array_push($combine, $matches);
            $i++;
            }

            foreach($combine as $combined) {
                echo $combined . ' ';
            }
        }       
    }       
}

【问题讨论】:

  • 您可以通过explode() 将单词排成一行,或者,也许更好的是,使用php.net/manual/sr/function.str-word-count.php 获取它们,然后将整个单词而不是单词部分进行匹配。
  • 所以将单词放入数组中,并为所有单词运行此匹配?让我试一试
  • 是的,我什至不会使用正则表达式,您可以检查获取值是否为 in_array()?
  • 正则表达式解释了部分输入的任何单词。因此,在“Apple”一词中输入“app”将获得全部价值。
  • 我将行列数组写为: $words = explode(' ', $line);但是,如果我为每个运行正则表达式,我似乎无法获得正确的逻辑。有什么想法吗?

标签: php search


【解决方案1】:

你最好把行分成单词,这样更容易匹配

【讨论】:

  • 是的。您可以将“单词”定义为a-Z0-9'"
  • 或者只是将字符串划分为字符,然后检索它们直到出现''|','|'.'|';'|':'。你会有一个单词然后匹配它用户输入,如果匹配则打印字符串(行)。
  • 我用过:$words = explode(' ', $line);这将每个单词放入数组的字符串中,但是我不确定如何处理它,并让它解析原始行。我是否只是让它找到单词 str_replace with class,然后将数组变回句子?
  • 查看更新的代码。这很好用。我自己想出了剩下的部分。
【解决方案2】:

我认为这样可以:

    <form action="" method="post">
    <h4>Search Object In Text File:</h4>
    <input type="text" name="search" value="">
    <input type="submit" value="Submit" name="Submit">
    </form>
    <?php
        $filename="tekst.txt";
        $lines = file($filename, FILE_IGNORE_NEW_LINES);

        if ( !is_array($lines) ) {
            echo 'Cannot create array from file';
        }

        //---- Scans and Displays Lines

        if(isset($_POST['search']))    
$submission = $_POST['search'];
        scanLines($lines,$submission);

        function scanLines($lines, $submission) {
            foreach($lines as $line) {
                $word_arr=str_word_count($line,1);
                $length=count($word_arr);
                for($i=0;$i<$length;$i++) {

                    if(preg_match("#$submission#",$word_arr[$i],$match)) {
                        $word_arr[$i]='<span class="highlight">'.$word_arr[$i].'</span>';
                        $new_line=implode(' ',$word_arr);
                        echo $new_line.'<br>';
                    }

                }

            }

        }

        ?>

因此,如果您想搜索单词的任何部分,并突出显示整个单词,而不仅仅是匹配的部分。对于完整(更严格)的全词搜索,您可以使用简单的 in_array() 函数。

【讨论】:

  • 我解决了这个问题,查看更新的代码。不过谢谢!