【问题标题】:Replace words - Ignore words between brackets替换单词 - 忽略括号之间的单词
【发布时间】:2011-03-06 11:21:04
【问题描述】:

我正在使用 ubb 解析器将括号内的多个代码转换为 html 代码。我也想使用字符串替换器来替换一些不需要的单词。

现在,我正在使用这个:

foreach($f AS $value) {
            $escapeNamesArray[] = '/'.$value['woord'].'/i';
            $escapeNamesReplace[] = '<span style="color: gray;">'.$value['vervanging'].'</span>';
        }

        $string = preg_replace($escapeNamesArray, $escapeNamesReplace, $string);

当我想将单词“Hello”替换为“Hey”时,一切正常。但是当我把“你好”这个词放在括号之间时,例如:

[url=http://www.hello.com]kdskdsds[/url]

“你好”这个词也被替换了。如何更改 preg_replace 函数的模式以忽略括号之间的单词?

感谢您的回复!

【问题讨论】:

    标签: php


    【解决方案1】:

    我建议使用每个变量并在左括号和右括号处拆分。 如果它在左括号处拆分,那么您知道它包含一个左括号。在左括号左侧的字符串上调用替换(调用 var1)。然后在右括号上调用 split ,您知道左边的字符串是括号的内容,因此将其连接到 var 1(称为 var2)。然后调用 replace 到最后一个拆分右侧的字符串,因为它必须在右括号之外,并将结果连接到 var2。

    例子:

    $exampleStr  = "[url=http://www.hello.com]kdskdsds[/url]";
    $piecesOfString = explode("[", $exampleStr);
    // $piecesOfString[0] = "" --> before the opening bracket so if there was anything there you would have to replace
    // $piecesOfString[1] = "url=http://www.hello.com]kdskdsds"
    // $piecesOfString[2] = "/url]";"
    
    $piecesOfStringSecond = explode("]", $piecesOfString[1]);
    // $piecesOfStringSecond[0] = "url=http://www.hello.com" within the brackets so don't replace
    // $piecesOfStringSecond[1] = "kdskdsds" //outside bracket so replace
    
    
    $piecesOfStringSecond = explode("]", $piecesOfString[2]);
    // $piecesOfStringSecond[0] = "/url" within the brackets so don't replace
    // $piecesOfStringSecond[1] = "" //outside bracket so if length > 0 replace
    

    我没有检查过这个,我用伪代码给你这个,但是:

    $exampleStr  = "begin[url=http://www.hello.com]kdskdsds[/url]between[url=http://www.second.com]dsfafa[/url]between2[url=http://www.third.com]kjhjkhk[/url]end";
    $piecesOfStringOpen = explode("[", $exampleStr);  //splits the string at the "["
    for integer j = 0 to length of $piecesOfStringOpen {
       if (j == 0) { // you know it will be the first part "begin"
          // call replace on $piecesOfStringOpen[j] because you know it is outside of brackets
       } else {  
          //this will include:
          //  $piecesOfStringOpen[1] = "url=http://www.hello.com]kdskdsds"
          //  $piecesOfStringOpen[2] = "/url]between"
          //  $piecesOfStringOpen[3] = "url=http://www.second.com]dsfafa"
          //  etc
          $piecesOfStringClose = explode("]", $exampleStr);  //splits the string at the "]"
          for integer k = 0 to length of $piecesOfStringClose {
             //if k == 0 then it was inside bracket, is a url and don't replace
             //elsif k == 1 then it was outside bracket and you want to replace
          }
       }
    }
    

    【讨论】:

    • 你能给我一个简短的例子吗,因为我不明白你的意思。
    • 当我有一个包含多个 UBB 标签的长文本时,按照你的方式来做是一项非常困难的任务,不是吗?
    • 可能有更简单的方法,但如果您保证不会有任何嵌入或不匹配的括号,这就是我所看到的。
    【解决方案2】:

    在类似 HTMl 的情况下使用 preg_replace 经常会变成一个泥坑。我强烈建议您找到解决此问题的其他方法。

    我建议让解析器先完成它的工作,将所有内容都转换为有效的 XHTML。然后使用 SimpleXMLElement 或 DOMDocument 之类的东西来解析文档。然后,您可以遍历对象,替换每个元素中的错误字符串。完成后,将其转换回 XHTML 字符串。

    这个解决方案涉及更多一点,但它更健壮、更灵活,尤其是当您决定稍后添加更多过滤器和替换时。

    【讨论】:

    • 恐怕这对我目前的情况来说太严格了。我不使用 DOMparser,如果可能的话,我想通过类似的 preg_replace 来做到这一点。
    【解决方案3】:

    Lucas 是对的,但这只是对现有代码的简单更改:

    您只需要在 [ ] 之间添加确保其唯一匹配的单词

    我刚刚在您的模式数组中添加了 [ 和 ](您需要将它们转义,因为它们通常用于正则表达式字符数组)。这是更新的代码:

    foreach($f AS $value)
    {
    $escapeNamesArray[] = '/ '.$value['woord'].' /i';
    $escapeNamesReplace[] = '<span style="color: gray;">'.$value['vervanging'].'</span>';
    }
    
    $string = preg_replace($escapeNamesArray, $escapeNamesReplace, $string);
    

    这是唯一实际更改的行:

    $escapeNamesArray[] = '/ '.$value['woord'].' /i';
    

    这适用于[whatever] [ whatever] [whatever ] 但不适用于[ whatever ]

    我还没有机会对此进行测试,但它应该可以工作。

    编辑:稍微更改代码,请再看一下:o)

    【讨论】:

    • 我认为他们正试图做完全相反的事情:只替换在 BBCode 标记之外找到的匹配项。
    • 感谢您的回复,但我想忽略括号之间的文字,所以与您的帖子相反。
    • 我的申请,再次,我没有时间测试,但上面编辑的代码应该可以工作
    • 不幸的是,这不起作用:(。括号中的单词也被替换了。
    • 对于如此多的试验和错误,我深表歉意,但正如我所提到的,我目前不在 PC 上进行测试。尝试更新的解决方案。如果这不起作用,我去找另一台电脑:oP
    【解决方案4】:

    您可以使用BBCode PECL extension 为您完成繁重的工作。看看这个:

    <?php
    
    function filterWords($content, $argument) {
    
      $badWordList = array(
        'complex',
        'regular expressions',
        'O(n^2)'
      );
    
      return str_ireplace($badWordList, '', $content);
    }
    
    $bbcodeParserConfig = array(
      ''    => array(
                    'type' => BBCODE_TYPE_ROOT,
        'content_handling' => 'filterWords'
      ),
      'url' => array(
                    'type' => BBCODE_TYPE_OPTARG,
                'open_tag' => '<a href="{PARAM}">',
               'close_tag' => '</a>',
             'default_arg' => '{CONTENT}',
                  'childs' => ''
      )
    );
    
    $bbcodeParser = bbcode_create($bbcodeParserConfig);
    
    $content = 'This is a complex url that [url=http://www.example.com]tells you nothing about regular expressions or O(n^2) algorithms[/url] and thankfully so!';
    
    var_dump(bbcode_parse($bbcodeParser, $content));
    

    还有一个BBCode parser written in PHP

    【讨论】:

      猜你喜欢
      • 2017-09-03
      • 2020-05-08
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多