Javascript 带有非捕获组的正则表达式作为两个备选方案

Javascript regex with non-capturing group as two alternatives

我想创建一个正则表达式,它允许您输入 NameSurname 等值。但我有一些限制:

您的正则表达式在某些地方 "too verbose",例如:

  • {1} 根本不需要。默认重复计数仅为 1。
  • {0,1} 可以简写为 ?.
  • 不需要'前面的\

您还使用了两种情况 (?= ... ) - 正面前瞻, 这里完全不需要。

Wiktor 提出的正则表达式几乎可以,但我会更改最后一个 *?,因为你提到 只有一个 可选姓氏(不是很多)。

所以我的提议是:

^[A-ZÀ-Ž][a-zà-ž]+(?:[\s'-][A-ZÀ-Ž][a-zà-ž]+)?$

描述:

  • ^ - 源字符串的开始。
  • [A-ZÀ-Ž] - 大写字母(名称的开头)。
  • [a-zà-ž]+ - 一系列小写字母(名称的其余部分)。
  • (?: - 一个非捕获组,由于它后面有 ? 需要。
    • [\s'-] - 白色字符或撇号或减号 (名字和姓氏之间的分隔符)。
    • [A-ZÀ-Ž][a-zà-ž]+ - 姓氏 - 就像名字一样。
  • )? - 非捕获组结束,可选。而不是 ?, Wiktor 提议*,允许许多 个姓氏。
  • $ - 源字符串结束。

所以非捕获组设置为容器:

  • 分隔符,
  • 姓氏。

可选(?),作为姓氏(连同前面的分隔符) 可能不存在。

也许 \s 应该只替换为 space,因为 \s 匹配 还有一个 Tab'\n' 我认为,这些字符不应该被允许 作为分隔符。

您需要分别匹配大小写字母。目前,您的 À-ž 欧洲字母范围包括所有小写和大写字母,甚至包括一些非字母。

这是您需要的范围:

大写(基本欧文)

  • 基本拉丁语 - 大写拉丁字母表:[A-Z]
  • 拉丁语 1 增补 — 字母项目 - 大写:[À-ÖØ-Þ]
  • 拉丁语扩展 A — 欧洲拉丁语 - 大写字母:[ĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJijĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒœŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸŹŻŽ]

小写(基本欧文)

  • 基本拉丁语 - 小写拉丁字母表:[a-z]
  • 拉丁语 1 增补 — 字母项目 - 小写:[ß-öø-ÿ]
  • 拉丁语扩展 A - 欧洲拉丁语 - 小写字母:[žſāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľŀłńņňŋōŏőŕŗřśŝşšţťŧũūŭůűųŵŷźż]

您需要的图案是

/^[UPPER][lower]+(?:[\s'-][UPPER][lower]+)*$/

其中UPPERlower是大小写字母ranges/sets.

所以,让我们构建模式。

var upper = '[A-ZÀ-ÖØ-ÞĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJijĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒœŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸŹŻŽ]';
var lower = '[a-zß-öø-ÿžſāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľŀłńņňŋōŏőŕŗřśŝşšţťŧũūŭůűųŵŷźż]';
var rx = new RegExp("^" + upper + lower + "+(?:[\s'-]" + upper + lower + "+)*$");
// Let's test
var tests = ['Test ','Test - ','Test-',' test','Test-test','TTest','Test\'test','Test','Test-Test','Test Test','Test\'Test', 'Łóźćż\'żłóźćęą'];
for (var s of tests) {
  console.log(s, '=>', rx.test(s))
}

注意欧洲语言中可以使用的字母更多。更多详情请参考Unicode Utilities

注意 2:如果您打算只支持 Chrome 和其他 ECMAScript 2018 兼容浏览器,您可以使用

console.log(  // ONLY WORKS IN ECMASCRIPT 2018 COMPATIBLE JS ENVIRONMENTS
  /^\p{Lu}\p{Ll}+(?:[\s'-]\p{Lu}\p{Ll}+)*$/u.test("Test'Ťĕśţ")
);

Java定义:

String pattern = "(?U)^\p{Lu}\p{Ll}+(?:[\s'-]\p{Lu}\p{Ll}+)*$";

如果您在 Java matches() 方法中使用它,请删除 ^$,因为它们在那里是多余的。