【问题标题】:preg_match to find words with capitals and successive capitalized wordspreg_match 查找带有大写字母和连续大写单词的单词
【发布时间】:2014-11-28 21:49:51
【问题描述】:

我正在尝试通过仅过滤掉符合以下条件的单词来匹配字符串中的关键字:

  • 包含大写字母的单词,例如“iPhone”或“camelCase”
  • 连续大写单词组,例如“Pittsburgh Steelers”或“Oscar De La Hoya”
  • 结合上述标准,如“iPhone 5”或“MIB 2”(也将数字视为大写)
  • 折叠所有非字符/数字,因此“O'Donnell's”将变为“ODonnells”,“Wi-fi...”将变为“Wifi”

例子:

$string = "Joe O'Donnell and Oscar De La Hoya went to a Pittsburgh Steelers game on Sunday, where Joe lost his iPhone 5, so he borrowed Oscar's iPad";

preg_match_all("/[A-Z][a-z]*/",$string,$match_words); // incorrect expression

// desired result for $match_words should be: 
// array(Joe ODonnell, Oscar De La Hoya, Pittsburgh Steelers, Sunday, Joe, iPhone 5, Oscars, iPad)

谢谢

【问题讨论】:

  • 必须是 preg_match 吗?是否也可以接受不同的解决方案?
  • @BrianGlaz 当然。什么都行。显然效率越高越好。
  • @John 高效且防弹:)

标签: php regex preg-match-all


【解决方案1】:

你可以使用这样的正则表达式:

\b((?:[A-Z]['a-z]*\s*\d*)+)\b|\b((?:[a-z]*[A-Z]['a-z]*\s*\d*)+)\b

Working demo

比赛信息:

MATCH 1
1.  [0-14]  `Joe O'Donnell `
MATCH 2
1.  [18-35] `Oscar De La Hoya `
MATCH 3
1.  [45-65] `Pittsburgh Steelers `
MATCH 4
1.  [73-79] `Sunday`
MATCH 5
1.  [87-91] `Joe `
MATCH 6
2.  [100-108]   `iPhone 5`
MATCH 7
1.  [125-133]   `Oscar's `
MATCH 8
2.  [133-137]   `iPad`

正则表达式由两种模式组成:

\b((?:[A-Z]['a-z]*\s*\d*)+)\b       ---> Match words like Joe O'Connels or Oscar De La Hoya
|
\b((?:[a-z]*[A-Z]['a-z]*\s*\d*)+)\b ---> Match words like iPad or iPhone

顺便说一句,如果您查看结果,它的末尾有一个尾随空格,您可以对结果进行修剪以进行清理。

【讨论】:

  • 谢谢。根据我的 OP 并没有摆脱单引号,但我可以在修剪后使用 str_replace 轻松摆脱它们。为我工作。干杯。
  • @John 很高兴为您提供帮助。感谢您的打勾
  • 刚刚在检查 Daniel 的回答时注意到“iPad”的匹配实际上应该是“Oscars iPad”(尽管我在最初的问题中搞砸了)。
  • @John 我明白了,我会检查一下
【解决方案2】:

您可以先删除所有非字母数字字符:

$string2 = preg_replace("/[^a-zA-Z0-9\s]/", "", $string);

然后使用preg_split 而不是preg_replace 将字符串拆分为完全小写的单词序列。

 $match_words = preg_split("/ ([a-z]| )+ /", $string2);

(如果不介意$string被销毁,可以将$string2替换为$string

这适用于您提供的示例,但请考虑您希望您的程序如何以较少净化的输入运行。例如,"Foo Bar"(两个空格)将被拆分为两个元素,而"Foo Bar"(一个空格)将保留为一个元素。如果您不担心速度,可以使用另一个 preg_replace 将任何空白序列替换为单个空格。

【讨论】:

  • 这很接近,但它从“iPhone”和“iPad”中去除了“i”
  • 很好,谢谢约翰! preg_spit 中的表达式应该是 "/ ([a-z]| )+ /" 而不是 "/ ([a-z]| )+/"。我已经编辑了原始帖子以反映这一点。
  • 谢谢丹尼尔。我已经足够接近接受 Fede 的回答,但这完美地完成了这项工作。
【解决方案3】:

除了 Fede 的甜蜜回答,这将是您的新 PHP 代码:

$string = "Joe O'Donnell and Oscar De La Hoya went to a Pittsburgh Steelers game on Sunday, where Joe lost his iPhone 5, so he borrowed Oscar's iPad";

preg_match_all("/\b((?:[A-Z]['a-z]*\s*\d*)+)\b|\b((?:[a-z]*[A-Z]['a-z]*\s*\d*)+)\b/", $string, $matches);

print_r($matches[0]);

$matches[0] 将是您的匹配数组。

【讨论】:

  • 感谢凯利的澄清。
【解决方案4】:

您可以在这里使用 PHP 的 ctype_lower 函数!

<?php

$string = "Joe O'Donnell and Oscar De La Hoya went to a Pittsburgh Steelers game on Sunday, where Joe lost his iPhone 5, so he borrowed Oscar's iPad";

$words = $temp = array();

// Loop through the string after turning it into an array (by spaces)
foreach (explode(" ", $string) as $word) {
    // Check if the word is lowercase and is not a number
    if (ctype_lower($word) && !is_numeric($word)) {
        if (empty($temp)) continue; // Don't add it if there's nothing to add

        // Add the words found up until this point (from the last point) into the words array, as a string
        $words[] = implode(" ", $temp);

        // Reset the temp array so we can look for new words and continue
        $temp = array();
        continue;
    }

    // Add this word to the words array
    $temp[] = $word;
}

$words[] = implode(" ", $temp);

// Print the words that have uppercase characters
printf("<pre>%s</pre>", print_r($words, true));

返回:

Array
(
    [0] => Joe O'Donnell
    [1] => Oscar De La Hoya
    [2] => Pittsburgh Steelers
    [3] => Sunday,
    [4] => Joe
    [5] => iPhone 5,
    [6] => Oscar's iPad
)

【讨论】:

  • 感谢 aelieo。然而,似乎缺少“奥斯卡的 iPad”的匹配项。
  • 你是对的!循环完成后我忘记添加最后一个循环集合。我更新了我的帖子以反映使其正常工作的更改。
【解决方案5】:

除了 Fede、Kelly 和 Daniel,还有 2 个重音语言的替代方案

使用preg_split

$capitalized_words = preg_split("/ ([a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]| )+ /u", $string);

使用preg_match_all

//with 'u' flag 
preg_match_all("/\b((?:[A-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝÆ]['a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]*\s*\d*)+)\b|\b((?:[a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]*[A-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝÆ]['a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]*\s*\d*)+)\b/u", $string, $capitalized_words);

使用preg_match_alltrim 的函数

function get_capitalized_words($string){
    $capitalized_words=array();

    //with 'u' flag 
    preg_match_all("/\b((?:[A-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝÆ]['a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]*\s*\d*)+)\b|\b((?:[a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]*[A-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝÆ]['a-zàèìòùáéíóúýâêîôûãñõäëïöüÿçßøåæœ]*\s*\d*)+)\b/u", $string, $matches);

    if(isset($matches[0])){
        $capitalized_words=array_map('trim',$matches[0]);
    }

    return $capitalized_words;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多