关于字符串:正则表达式首字母大写超过3个字符的单词,并在连字符和撇号之后

Regex capitalise first letter of words more than 3 chars, and after hyphens and apostrophes

基本上…

我正在尝试对一个字符串执行自定义大写;我花了几个小时与regex斗争,但没有成功…

要求:

I need to capitalise:

  • If first word >3 chars: First letter of the first word.
  • If last word >3 chars: First letter of the last word.
  • Always: First letter following a hyphen or apostrophe.
  • (The final regex needs to be implementable into VB6)

    1
    2
    3
    4
    5
    6
    7
    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)

    到目前为止我得到的:

    我把两个正则表达式混在一起,它们几乎可以完成我需要的任务。然而,我尝试将它们合并到一个regex中,或者将其作为一个regex来编写,但都失败了。

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

    我的正则表达式:

    第一个和最后一个单词的第一个字母,但不限于超过3个字符的单词,并且不处理全字符串标点大写。

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

    所有单词的第一个字母,以及标点符号之后,其中超过3个字符但不排除中间单词,或在结尾处处理标点符号。

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

    问题

    How I can combine these two regex's to meet my requirements, or correct them enough that they can be used separately? Alternatively provide a different regex that meets the requirements.

    参考/相关来源材料:

    regex将每个单词的第一个字母大写,也可以在特殊字符(如破折号)之后

    带regex的字符串最后一个单词的第一个单词和第一个字母


    以下是我的一个regex方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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

    enter image description here

    我使用的regex是^[a-z](?=[a-zA-Z'-]{3})|\b[a-z](?=[a-zA-Z'-]{3,}$)|['-][a-z]。由于使用的所有字符都是我们想要变为大写或连字符/撇号的字母,因此我们可以将它们全部变为大写,而不必捕获任何字符。

    regex匹配3个选项:

    • ^[a-z](?=[a-zA-Z'-]{3})—字符串的开头(在我的例子中,是我使用Multiline=True以来的行),后跟一个小写的ASCII字母(消耗掉,以后再大写),后面有3个字符,字母或'-(不消耗,在lookahead中)
    • \b[a-z](?=[a-zA-Z'-]{3,}$)—一个单词边界\b,后面跟一个小写的ASCII字母(已使用),后面跟3个或更多的字母,或者'-,直到字符串的结尾(在我的例子中是line)。
    • ['-][a-z]—与'-匹配,然后是小写字母(字符串中的任意位置)。

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