【问题标题】:How do I get all words that begin with a capital letter following a specific string?如何获取在特定字符串后以大写字母开头的所有单词?
【发布时间】:2023-07-28 12:47:01
【问题描述】:

我有一些看起来像这样的文本:

Name is William Bob Francis Ford Coppola-Mr-Cool King-Of-The-Mountain is a fake name.

我想对该字符串运行一个正则表达式并取出

William Bob Francis Ford Coppola-Mr-Cool King-Of-The-Mountain 

作为匹配。

我当前的正则表达式如下所示:

/\b((NAME\s\s*)(((\s*\,*\s*)? *)(([A-Z\'\-])([A-Za-z\'\-]+)*\s*){2,})?)\b/ig

它完成了我想要的大部分工作,但并不完美。它不仅获取名称,还获取名称后面的“is a”,如下所示:

"William Bob Francis Ford Coppola-Mr-Cool King-Of-The-Mountain is a"

什么是正则表达式,仅获取“名称”标签后以大写字母开头的单词,并在下一个单词以空格后的小写字母开头时结束?

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    你觉得/Name ((?:[A-Z]\w+[ -]?)+)/怎么样?

    正则表达式101:https://regex101.com/r/BFJBpZ/1

    【讨论】:

    • 这真的很接近。它唯一缺少的是捕获像 O'neil 或 O'Leary 这样的名字。如何添加对包含撇号的名称的检查?非常感谢!!!
    • \w 是单词字符(字母、数字和下划线,包括适合此类别的 unicode 字符)的字符类。您可以使用其他字符或其他自定义创建字符类,例如:[\w'] 请参阅docs。 (这是针对 Perl 正则表达式的,因为它已标记在问题上,包括 PCRE 在内的其他正则表达式引擎可能具有不同的功能。)
    【解决方案2】:

    你可以使用:

    Name\b[\sa-z]*\K(?:[A-Z][a-z]+[\s-]*)+(?=\s[a-z])
    

    在哪里

    • \K 在匹配 Name 后跟一些小写单词后重置匹配的起点
    • (?:[A-Z][a-z]+[\s-]*)+ 将匹配所有以大写字母开头的单词
    • (?=\s[a-z])添加以下单词以小写字母开头的约束

    演示: https://regex101.com/r/WBrdFU/1/

    注意事项:

    你不应该在你的正则表达式中使用i 选项,如果你这样做了 您的 char 类 [A-Z] 将同时匹配大写 字母,还有小写字母......这会阻止你 选择以大写字母开头的单词!!!

    添加带撇号的名称

    Name\b[\sa-z]*\K(?:[A-Z][a-z'\s-]*?)+(?=\s[a-z])
    

    演示https://regex101.com/r/WBrdFU/3/

    【讨论】:

    • 这对 unicode 不敏感,想象一下某人的名字中带有 Ñ,它将超出 A-Z 的范围。
    【解决方案3】:

    我的猜测是,如果我们在想要的输出之后总是有is,这个简单的表达式可能会起作用:

    Name is (.+?) is.+
    

    测试

    use strict;
    
    my $str = 'Name is William Bob Francis Ford Coppola-Mr-Cool King-Of-The-Mountain is a fake name.
    ';
    my $regex = qr/Name is (.+?) is.+/mp;
    
    if ( $str =~ /$regex/g ) {
      print "Whole match is ${^MATCH} and its start/end positions can be obtained via \$-[0] and \$+[0]\n";
      # print "Capture Group 1 is $1 and its start/end positions can be obtained via \$-[1] and \$+[1]\n";
      # print "Capture Group 2 is $2 ... and so on\n";
    }
    
    # ${^POSTMATCH} and ${^PREMATCH} are also available with the use of '/p'
    # Named capture groups can be called via $+{name}
    

    Demo

    正则表达式电路

    jex.im 可视化正则表达式:

    建议

    zdim 建议:

    也许,因为它可能不是“is”,而是任何小写单词(所以在 字边界),类似于/\b([A-Z].+?)\b[a-z.!?]/ ... (可能需要调整,特别是对于可能的句子结尾 在名字之后)?

    【讨论】:

    • 好主意 --- 也许,因为它可能不是“is”,只是任何小写单词(所以在单词边界之后),类似于 /\b([A-Z].+?)\b[a-z.!?]/ ...(可能需要调整,特别是对于名称后可能的句子结尾)?
    【解决方案4】:

    这在我使用 regex101.com 进行测试时有效。请检查并告诉我这是否适合您

      /Name is (([\s]*[A-Z][-a-z]*)*)/
    

    第 1 组有这个William Bob Francis Ford Coppola-Mr-Cool King-Of-The-Mountain

    并在下面的这个链接上测试它

    https://regex101.com/r/M2V2in/2

    【讨论】:

      最近更新 更多