代码之家  ›  专栏  ›  技术社区  ›  fire

拆分单词,但不包含HTML

php
  •  1
  • fire  · 技术社区  · 14 年前

    我需要一个函数或一些regex来拆分字符串中的空格,但要将HTML标记视为一个单词。

    $str = 'one two <a href="">three</a> four';
    $x = explode(" ", $str);
    print_r($x);
    
    /* Returns:
      Array
    (
        [0] => one
        [1] => two
        [2] => <a
        [3] => href="">three</a>
        [4] => four
    )
    
    Looking for way to return:
    
    Array
    (
        [0] => one
        [1] => two
        [2] => <a href="">three</a>
        [3] => four
    )
    
    */
    

    有什么想法吗?谢谢

    4 回复  |  直到 14 年前
        1
  •  2
  •   AnimeCYC    14 年前

    这比上面的简单一点,还没有完全测试过,但是试一下。

    $str = 'one two <a href="">three</a> four';
    
    if(preg_match_all('%(<[^<]+.*?>|[^\s]+)%', $str, $matches)) {
        array_shift($matches);
        print_r($matches);
    }
    

    下面是另一个版本,我测试了大约5分钟,效果更好:

    $str = 'one two <a href="omfg hi I have spaces"> three</a> four <script type="javascript"> var a = "hello"; </script><random tag>la la la la<nested>hello?</nested></random tag>';
    
    if(preg_match_all('%(<[^<]+.*?>|[^\s]+)%', preg_replace('%([\s]\<|\>[\s])%', '$1', $str), $matches)) {
        array_shift($matches);
        echo '<pre>';
        print_r($matches);
        echo '</pre>';
    }
    
        2
  •  2
  •   berkes    14 年前
    preg_split('/(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\1>)|| /, $text)
    

    这有时会奏效。它可以在一个标记集上拆分,也可以在一个空格上拆分。

    然而,你想要的并不是那么简单。您应该涵盖所有嵌套标记、内容有空格的标记([a href]foo bar baz[/a])等情况。 为此,最好实现适当的XML(HTML)解析器。

    但在我看来,你有这个数组的目的。是数词吗?如果是这样,解决方案将是一个更简单的函数调用,它从文本(strip_tags())中删除所有HTML,然后应用分词器并对其进行计数。

        3
  •  0
  •   Rob Stevenson-Leggett    14 年前

    可以在使用explode前后对字符串执行regex替换。

    所以会像爆炸一样

    <a_href="">test</a>
    

    除了任何简单的例子之外,尽管您谈论的是解析HTML,这对于regex来说不是一件好事。

    这里有很多关于解析HTML的问题。也许你可以适应他们。

        4
  •  0
  •   Fosco    14 年前

    我编写并测试了这个自定义函数。试一试,告诉我你的想法。

    function fireSplit($str) {
      if (strpos($str,"<") === FALSE) return explode(" ",$str);
      $str = trim($str);
      $out = array();
      $curIdx = 0;
      $endIdx = strlen($str) -1;
    
      while ($curIdx <= $endIdx) {
            if (substr($str,$curIdx,1) == " ") {
                  $curIdx += 1;
                  continue;
            }
            $nextspace = strpos($str," ",$curIdx);
            $nexttag = strpos($str,"<",$curIdx);
            $nexttag2 = strpos($str,"/",$nexttag);
            $nexttag3 = strpos($str,">",$nexttag2);
    
            if ($nextspace === FALSE) {
                  $out[] = substr($str,$curIdx);
                  $curIdx = $endIdx + 1;
                  continue;
            }
    
            if ($nexttag !== FALSE && $nexttag < $nextspace && $nexttag2 !== FALSE && $nexttag3 !== FALSE) {
                  $out[] = substr($str,$curIdx,($nexttag3 - $curIdx + 1));
                  $curIdx = $nexttag3 + 1;
            } else {
                  $out[] = substr($str,$curIdx,($nextspace - $curIdx));
                  $curIdx = $nextspace;
            }
      }
    return $out;
    }
    

    我打电话给你:

    fireSplit("one two <a href=\"haha\">three</a> four");
    fireSplit("a <b>strong</b> c d e f");
    

    它回来了:

    array(4) {
      [0]=>
      string(3) "one"
      [1]=>
      string(3) "two"
      [2]=>
      string(24) "<a href="haha">three</a>"
      [3]=>
      string(4) "four"
    }
    
    array(6) {
      [0]=>
      string(1) "a"
      [1]=>
      string(13) "<b>strong</b>"
      [2]=>
      string(1) "c"
      [3]=>
      string(1) "d"
      [4]=>
      string(1) "e"
      [5]=>
      string(1) "f"
    }