【问题标题】:Extract words from string with preg_match_all使用 preg_match_all 从字符串中提取单词
【发布时间】:2012-05-27 21:22:21
【问题描述】:

我不擅长正则表达式,但我想用它从字符串中提取单词。

我需要的单词至少要有 4 个字符,并且提供的字符串可以是 utf8。

示例字符串:

Sus azahares presentan gruesos pétalos blancos teñidos de rosa o violáceo en la parte externa, con numerosos estambres (20-40)。

期望的输出:

Array(
    [0] => azahares
    [1] => presentan
    [2] => gruesos
    [3] => pétalos
    [4] => blancos
    [5] => teñidos
    [6] => rosa
    [7] => violáceo
    [8] => parte
    [9] => externa
    [10] => numerosos
    [11] => estambres
)

【问题讨论】:

  • Explode 不好,我也知道如何使用 str_word_count 并使其与特殊的字符列表一起使用,但是我必须使用 foreach 来计算每个单词中的字符,我发现这是一个不必要的步骤。
  • 如果让你感觉更好,你可以使用 array_filter 代替 foreach:codepad.viper-7.com/AR0AEn

标签: php regex string keyword


【解决方案1】:

应该为你做这项工作

function extractCommonWords($string) {
    $stopWords = array('i','a','about','an','and','are','as','at','be','by','com','de','en','for','from','how','in','is','it','la','of','on','or','that','the','this','to','was','what','when','where','who','will','with','und','the','www');

    $string = preg_replace('/\s\s+/i', '', $string); //echo $string, "<br /><br />"; // replace whitespace
    $string = trim($string); // trim the string
    $string = preg_replace('/[^a-zA-Z0-9 -_]/', '', $string); // only take alphanumerical characters, but keep the spaces and dashes too…
    $string = strtolower($string); // make it lowercase

    preg_match_all('/([a-zA-Z]|\xC3[\x80-\x96\x98-\xB6\xB8-\xBF]|\xC5[\x92\x93\xA0\xA1\xB8\xBD\xBE]){4,}/', $string, $matchWords);
    $matchWords = $matchWords[0];

    foreach($matchWords as $key => $item) {
        if($item == '' || in_array(strtolower($item), $stopWords) || strlen($item) <= 3) {
            unset($matchWords[$key]);
        }
    }

    $wordCountArr = array();
    if(is_array($matchWords)) {
        foreach($matchWords as $key => $val) {
            $val = strtolower($val);
            if(isset($wordCountArr[$val])) {
                $wordCountArr[$val]++;
            } else {
                $wordCountArr[$val] = 1;
            }
        }
    }

    arsort($wordCountArr);
    $wordCountArr = array_slice($wordCountArr, 0, 10);
    return $wordCountArr;
}

【讨论】:

    【解决方案2】:

    如果要查找的单词是 UTF-8(根据规范至少 4 个字符长),由 ISO-8859-15 的字母字符组成(这对于西班牙语很好,但也适用于英语、德语、法语等):

    $n_words = preg_match_all('/([a-zA-Z]|\xC3[\x80-\x96\x98-\xB6\xB8-\xBF]|\xC5[\x92\x93\xA0\xA1\xB8\xBD\xBE]){4,}/', $str, $match_arr);
    $word_arr = $match_arr[0];
    

    【讨论】:

    • 这行得通。我没有注意到它有任何问题,希望我不会发现任何问题。谢谢@Walter Tross
    【解决方案3】:

    当您使用u 修饰符时,您可以使用以下模式(demo):

    preg_match_all('(\w{4,})u', $string, $matches);
    print_r($matches[0]);
    

    u modifier 表示:

    u (PCRE_UTF8):此修饰符打开与 Perl 不兼容的 PCRE 的附加功能。模式字符串被视为 UTF-8。此修饰符在 Unix 上的 PHP 4.1.0 或更高版本以及 win32 上的 PHP 4.2.3 中可用。自 PHP 4.3.5 起检查模式的 UTF-8 有效性。

    【讨论】:

    • 我无法使用此解决方案获得任何好的结果,但确实我不能使用 u 修饰符。无论如何谢谢
    【解决方案4】:

    您可以将下面的正则表达式用于简单的字符串。它将匹配任何最小长度 = 4 的非空白字符。

    preg_match_all('/(\S{4,})/i', $str, $m);
    

    现在$m[1] 包含您想要的数组。

    更新:

    正如 Gordon 所说,该模式也将匹配 '(20-40)'。可以使用此正则表达式删除不需要的数字:

    preg_match_all('/(\pL{4,})/iu', $str, $m);
    

    但我认为它只有在 PCRE 编译时支持 UTF-8 才有效。见PHP PCRE (regex) doesn't support UTF-8?。不过它可以在我的电脑上运行。

    【讨论】:

    • 它也会匹配“(20-40)”
    • 我知道我可以用正则表达式完成这项工作,只是我不知道如何编写模式。你是一个好的开始,我仍然希望有人改进这个模式。
    • @bdsnoobz 这个模式还可以,除了一个单词,其他都可以。我不能使用 u 修饰符,但没有它它也能很好地工作。
    • @flowfree 谢谢,效果很好。如果我想向数组中添加短于 4 位的数字怎么办?我需要得到超过 4 个字符的单词,但数字是任意位数
    • @flowfree 我不确定它是否正确,但我尝试过 /(\S{4,}|\d+)/i
    【解决方案5】:

    试试这个:

    $str='Sus azahares presentan gruesos pétalos blancos teñidos de rosa o violáceo en la parte externa, con numerosos estambres (20-40).';
    preg_match_all('/([^0-9\s]){4,}/i', $str, $matches);
    echo '<pre>';
    var_dump($matches);
    echo '</pre>';
    

    【讨论】:

    • 哎呀,缺少逗号符号 '/([^0-9\s,]){4,}/i' 字符类 [^] 中的插入符号用于否定结果。刚刚测试,输出应该和想要的结果一样
    • 对不起,这没有得到我期望的结果。
    【解决方案6】:

    用空格分解你的字符串(这将创建一个包含所有单词的数组),然后检查单词是否大于 4 个字母。

    //The string you want to explode
    $string = "Sus azahares presentan gruesos pétalos blancos teñidos de rosa o violáceo en la parte externa, con numerosos estambres."
    //explode your $string, which will create an array which we will call $words
    $words = explode(' ', $string);
    
    //for each $word in $words
    foreach($words as $word)
    {
        //check if $word length if larger then 4
        if(strlen($word) > 4)
        {
            //echo the $word
            echo $word;
        }
    }
    

    strlen();

    strlen — 获取字符串长度

    explode();

    explode — 按字符串拆分字符串

    【讨论】:

    • 按空间爆炸不好。此外,我试图避免额外的 foreach 来计算每个单词的字符数。
    • 如果您担心的是逗号和点,只需执行 str_replace 即可摆脱它们。而且您不需要额外的 foreach 循环来计算单词的长度。只需说 echo strlen($word);在当前的 foreach 中
    【解决方案7】:
    $string = Sus azahares presentan gruesos pétalos blancos teñidos de rosa o violáceo en la parte externa, con numerosos estambres
    
    $words = explode(' ', $string);
    echo $words[0];
    echo $words[1];
    

    等等

    【讨论】:

    • 这个解决方案不好。有些单词后面没有空格,有时它们有逗号或?或!。
    • 将你的字符串存储在一个数组中,如果它有一个逗号,一个接一个地取出每个单词,然后保存它的长度为 4 或更多的单词。我在课堂上,否则我会自己尝试一下:)
    猜你喜欢
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多