具有非捕获组的Javascript正则表达式是两种选择

时间:2018-07-02 16:43:49

标签: javascript regex regex-group

我想创建一个正则表达式,它允许您输入诸如NameSurname之类的值。但是我有一些限制:

  • 大写的首字母(只有一个),然后是其他小写字母
  • 在上一个之后,用户可以使用'-(空格),然后再应用与第一点相同的规则

我几乎实现了这一目标,但是仍然无法正常工作。这是我的创作:

/^[A-ZÀ-ž]{1}[a-zà-ž]+[\s\'-]{0,1}(?:(?=[\s\'-]{0,1})[A-ZÀ-ž]{1}[a-zà-ž]+|(?=[\s\'-]{0,1})[a-zà-ž]+)$/i

我想在Javascript中将其与功能.test(value)一起使用。不幸的是,它也接受这些:

  • Test
  • Test -
  • Test-
  • test
  • Test
  • Test-test
  • TTest
  • Test'test

我想被接受和允许的是那些:

  • Test
  • Test-Test
  • Test Test
  • Test'Test

我不知道我在做什么错以及如何解决这个问题……我在这里缺少什么?

2 个答案:

答案 0 :(得分:2)

您的正则表达式在某些地方“太冗长”,例如:

    完全不需要
  • {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应该用空格代替,因为\s匹配 也是Tab'\n',我认为,不应使用这些字符 作为分隔符。

答案 1 :(得分:1)

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

这是您需要的范围:

大写(基本欧洲语言)

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

小写(基本的欧洲语言)

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

您需要的模式是

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

其中UPPERlower是大写和小写字母范围/集。

所以,让我们构建模式。

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()方法中使用它,请删除^$,因为它们在那里多余。