正则表达式:将每个单词的首字母大写,包括特殊字符后面的字母,如破折号。

42
我使用这个方法将每个单词的首字母大写:
#(\s|^)([a-z0-9-_]+)#i

我希望它将特殊符号(如破折号-)后面的字母也大写。

现在显示为:

This Is A Test For-stackoverflow

我想要这个:

This Is A Test For-Stackoverflow


3
你是否需要对非ASCII字母(àü等)进行大写处理?你使用的是哪种语言? - Tim Pietzcker
你在问哪种语言的正则表达式? - JohnK
9个回答

36

+1表示计算单词边界,这里提供一个类似的JavaScript解决方案。该方案考虑了所有格:

var re = /(\b[a-z](?!\s))/g;
var s = "fort collins, croton-on-hudson, harper's ferry, coeur d'alene, o'fallon"; 
s = s.replace(re, function(x){return x.toUpperCase();});
console.log(s); // "Fort Collins, Croton-On-Hudson, Harper's Ferry, Coeur D'Alene, O'Fallon"

toUpperCase函数将整个单词大写。以下是解决方案: s.replace(re, function(x){return x.charAt(0).toUpperCase() + x.slice(1);}); - Polopollo
2
@Polopollo,在这种情况下,如果匹配的话,正则表达式只会全局返回一个字母。因此不需要额外的代码,应该原样工作。 - adam-beck
这种方法不适用于 OP 所要求的情况,因为单个字符无法大写。仅供像我一样来到这个问题的任何人参考。 - adam-beck
2
我担心这个不起作用:单词边界包括像“.”这样的东西。所以don't变成了Don'T - Anderas
@Anderas,这就是负向先行断言的作用:(?!\s)检查它之前是否有字符。另一方面,当像don't这样的单词后面跟着非空格、非字母数字字符(如逗号、句号或感叹号)时,这种方法会失败。最好在先行断言中使用单词边界:/(\b[a-z](?!\b))/g; - Guido Bouman
@GuidoBouman:您提出的正则表达式对于Coeur D'Alene和O'Fallon无法匹配。 - davemyron

20

一个简单的解决方案是使用词边界

#\b[a-z0-9-_]+#i

或者,您可以仅匹配几个字符:

#([\s\-_]|^)([a-z0-9-_]+)#i

2
@Tim - 我在艺术自由方面做了些改动,没有改变OP匹配字母的方式 - Simmer可能希望将字母作为输出,更改它们的颜色或其他内容。此外,我没有太多考虑,只有4分钟 :P - Kobi
1
有人能否添加一个 jsfiddle 的例子,这将会很有帮助。 - Pravin W
1
这是哪种语言的正则表达式? - JohnK
@JohnK - 这两个都很简单,应该适用于所有语言。 # 在这里是一个分隔符,因此您的语言可能需要 "\\b[a-z0-9-_]+" 和一个 IgnoreCase 标志。 - Kobi

13

要使用纯正则表达式,您必须使用\u

将此字符串转换为:

This Is A Test For-stackoverflow

变成

This Is A Test For-Stackoverflow

您必须使用(.+)-(.+)来捕获“-”前后的值,然后将其替换,您必须输入:

$1-\u$2

如果在bash中,您必须输入:

echo "This Is A Test For-stackoverflow" | sed 's/\(.\)-\(.\)/\1-\u\2/'


这个非常好用,谢谢。不过,你能否提供一下关于 \u 标记的文档链接吗?以及它是如何将第二组的首字母大写的呢? - Harshal
1
@Harshal,我不明白你的问题,但我会尝试回答。使用"\u"标志表示您要大写后面字符串的第一个字符。如果您使用表达式(.+)-(.+),则值$2对应于第二个括号内的内容,这就是为什么"u$2"将首字母大写,在此示例中它是 "S",来自stackoverflow。 - Jaime Roman
谢谢,更准确地说,我想知道是否有任何文档说明 "\u" 可以将首字母大写。它的效果符合预期,我只是想多了解一下这个标志。 - Harshal

8
实际上不需要匹配整个字符串,只需匹配第一个非大写字母,像这样:
'~\b([a-z])~'

3
在 JavaScript 中,我添加了 g,像这样 /\b([a-z])/g,以大写每个单词。 - Stalin Gino
1
我喜欢你可爱的回答@StalinGino,必须说这是我唯一能理解的回答。 - Danish
这符合要求。也请检查其他答案。 - anubhava

4
对于JavaScript而言,这里有一个适用于不同语言和字母表的解决方案:
const originalString = "this is a test for-stackoverflow"
const processedString = originalString.replace(/(?:^|\s|[-"'([{])+\S/g, (c) => c.toUpperCase())

\S匹配任何非空格字符,前面紧跟着字符串的开头^、空格\s或任何一个字符-"'([{,并将其替换为大写字母。


3

我使用JavaScript开发的解决方案

function capitalize(str) {
  var reg = /\b([a-zÁ-ú]{3,})/g;
  return string.replace(reg, (w) => w.charAt(0).toUpperCase() + w.slice(1));
}

使用 ES6 + JavaScript
const capitalize = str => 
    str.replace(/\b([a-zÁ-ú]{3,})/g, (w) => w.charAt(0).toUpperCase() + w.slice(1));



/<expression-here>/g
  1. [a-zÁ-ú] 这里我考虑了所有字母,包括大写和带重音的字母。 例如:sábado de Janeiro às 19hsexta-feira de janeiro às 21 e horas
  2. [a-zÁ-ú]{3,} 所以我将去除一些不够大的字母。
    例如:sábado de Janeiro às 19h。 sexta-feira de janeiro às 21 e horas
  3. \b([a-zÁ-ú]{3,}) 最后,我只保留所选的完整单词。必须使用()来隔离最后一个表达式以使其工作。
    例如:sábado de Janeiro às 19h。 sexta-feira de janeiro às 21 e horas

完成这一步后,我仅将更改应用于小写字母中的单词。

string.charAt(0).toUpperCase() + w.slice(1); // output -> Output

加入这两个。
str.replace(/\b(([a-zÁ-ú]){3,})/g, (w) => w.charAt(0).toUpperCase() + w.slice(1));

结果:
1月星期六晚上7点。 1月星期五晚上9点。


1

虽然纯正的正则表达式解决方案answer是准确的:

echo "This Is A Test For-stackoverflow" | sed 's/\(.\)-\(.\)/\1-\u\2/'

在使用任何大小写转换运算符时,应该注意:

\l            Change case of only the first character to the right lower case. (Note: lowercase 'L')
\L            Change case of all text to the right to lowercase.
\u            Change case of only the first character to the right to uppercase.
\U            Change case of all text to the right to uppercase.

应该使用结束分隔符:

\E

因此最终结果应该是:

echo "This Is A Test For-stackoverflow" | sed 's/\(.\)-\(.\)/\1-\u\E\2/'

1
Python解决方案:
>>> import re
>>> the_string = 'this is a test for stack-overflow'
>>> re.sub(r'(((?<=\s)|^|-)[a-z])', lambda x: x.group().upper(), the_string)
'This Is A Test For Stack-Overflow'

阅读关于 "正向后行断言" 的内容


-1

这将会使

R.E.A.C De Boeremeakers

r.e.a.c de boeremeakers

(?<=\A|[ .])(?<up>[a-z])(?=[a-z. ])

使用

    Dim matches As MatchCollection = Regex.Matches(inputText, "(?<=\A|[ .])(?<up>[a-z])(?=[a-z. ])")
    Dim outputText As New StringBuilder
    If matches(0).Index > 0 Then outputText.Append(inputText.Substring(0, matches(0).Index))
    index = matches(0).Index + matches(0).Length
    For Each Match As Match In matches
        Try
            outputText.Append(UCase(Match.Value))
            outputText.Append(inputText.Substring(Match.Index + 1, Match.NextMatch.Index - Match.Index - 1))
        Catch ex As Exception
            outputText.Append(inputText.Substring(Match.Index + 1, inputText.Length - Match.Index - 1))
        End Try
    Next

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接