【问题标题】:Regex capitalise first letter of words more than 3 chars, and after hyphens and apostrophes正则表达式将超过 3 个字符的单词首字母大写,并在连字符和撇号之后
【发布时间】:2016-10-15 07:37:22
【问题描述】:

基本上...

我正在尝试对字符串执行自定义大写;我花了几个小时与 Regex 战斗,但无济于事......

要求:

我需要大写:

  1. 如果第一个单词 >3 个字符:第一个单词的第一个字母。
  2. 如果最后一个单词 >3 个字符:最后一个单词的第一个字母。
  3. 始终:连字符或撇号后的第一个字母。

(最终的正则表达式需要在 VB6 中实现)

Examples:
anne-marie          >  Anne-Marie          // 1st letter of first word + after hyphen
vom schattenreich   >  vom Schattenreich   // 1st letter of last word
will it work-or-not >  Will it Work-Or-Not // 1st letter of outer words + after hyphens
seth o'callaghan    >  Seth O'Callaghan    // 1st letter of outer words + after apostrophe
first and last only >  First and last Only // 1st letter of outer words (excl. middle)
sarah jane o'brien  >  Sarah jane O'Brien  // 1st letter of outer words (excl. middle)

到目前为止我的收获:

我将两个正则表达式拼凑在一起,它们之间几乎可以完成我所需要的。然而,我尝试将它们合并到单个正则表达式中或将其编写为一个正则表达式都失败了。

我的主要困难是我的部分大写仅适用于第一个和最后一个单词,而标点符号特定的大写需要适用于整个字符串。但我对正则表达式的了解还不够,无法确定是否可以使用一个表达式。

我的正则表达式:

First letter of First and Last words 但不限于超过 3 个字符的单词,并且不处理完整的字符串标点符号大写

^([a-zA-Z]).*\s([a-zA-Z])[a-zA-Z-]+$

First letter of all words, and after punctuation, where more than 3 chars 但不排除中间词,或在末尾处理标点符号

(\b[a-zA-Z](?=[a-zA-Z-']{3}))

问题

如何结合这两个正则表达式来满足我的要求,或者更正它们以使它们可以单独使用?或者提供满足要求的不同正则表达式。

参考/相关源材料:

Regex capitalize first letter every word, also after a special character like a dash

First word and first letter of last word of string with Regex

【问题讨论】:

    标签: regex string replace vb6 capitalization


    【解决方案1】:

    这是我的一种正则表达式方法:

    Sub ReplaceAndTurnUppercase()
    
    Dim reg As RegExp
    Dim res As String
    
    Set reg = New RegExp
    With reg
        .Pattern = "^[a-z](?=[a-zA-Z'-]{3})|\b[a-zA-Z](?=[a-zA-Z'-]{3,}$)|['-][a-z]"
        .Global = True
        .MultiLine = True
    End With
    s = "anne-marie" & vbCrLf & "vom schattenreich" & vbCrLf & "will it work-or-not" & vbCrLf & "seth o'callaghan" & vbCrLf & "first and last only" & vbCrLf & "sarah jane o'brien"
    res = s
    For Each Match In reg.Execute(s)
        If Len(Match.Value) > 0 Then
            res = Left(res, Match.FirstIndex) & UCase(Match.Value) & Mid(res, Match.FirstIndex + Len(Match.Value) + 1)
        End If
    Next Match
    Debug.Print res ' Demo part
    
    End Sub
    

    我使用的正则表达式是^[a-z](?=[a-zA-Z'-]{3})|\b[a-z](?=[a-zA-Z'-]{3,}$)|['-][a-z]。由于所消耗的所有字符只是我们想要转为大写或连字符/撇号的字母,因此我们可以将它们全部转为大写,而无需捕获其中任何一个。

    正则表达式匹配 3 个替代项:

    • ^[a-z](?=[a-zA-Z'-]{3}) - 字符串的开头(在我的例子中,是因为我使用了Multiline=True 之后的行),后跟一个小写的 ASCII 字母(已使用,稍后变为大写),后面有 3 个字符,字母或 ' 或 @987654330 @(未消耗,在前瞻内)
    • \b[a-z](?=[a-zA-Z'-]{3,}$) - 单词边界 \b 后跟一个小写 ASCII 字母(已使用),后跟 3 个或更多字母或 '- 直到字符串的末尾(在我的情况下为行)
    • ['-][a-z] - 匹配 '-,然后是小写字母(字符串中的任何位置)。

    res = Left(res, match.FirstIndex) & UCase(match.Value) & Mid(res, match.FirstIndex + Len(match.Value) + 1) 行完成了这项工作:它只是将字符串的一部分获取到找到的索引,然后添加修改后的文本,并附加其余部分。

    【讨论】:

    • 感谢您的快速响应,非常接近!不幸的是,我只需要匹配超过 3 个字符的第一个和最后一个单词。见regex101.com/r/mX4wH6/3
    • 那么您能否更新示例输入文本?我只检查了你发布的那些。
    • 不能用另一个OR处理吗? (请原谅我缺乏正则表达式知识)
    • 看来我夸大了正则表达式的复杂性 :)
    猜你喜欢
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多