Javascript 带有非捕获组的正则表达式作为两个备选方案
Javascript regex with non-capturing group as two alternatives
我想创建一个正则表达式,它允许您输入 Name
和 Surname
等值。但我有一些限制:
- 大写第一个字母(只有一个)然后是其他小写字母
- 在前一个之后,用户可以使用
'
、-
或 </code>(空格),然后应用与第一点相同的规则</li>
</ul>
<p>我差不多做到了,但还是有些地方不能正常工作。这是我的创作:</p>
<pre><code>/^[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
我不知道我做错了什么以及如何解决这个问题...我在这里缺少什么?
您的正则表达式在某些地方 "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]+)*$/
其中UPPER
和lower
是大小写字母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()
方法中使用它,请删除 ^
和 $
,因为它们在那里是多余的。
我想创建一个正则表达式,它允许您输入 Name
和 Surname
等值。但我有一些限制:
- 大写第一个字母(只有一个)然后是其他小写字母
- 在前一个之后,用户可以使用
'
、-
或</code>(空格),然后应用与第一点相同的规则</li> </ul> <p>我差不多做到了,但还是有些地方不能正常工作。这是我的创作:</p> <pre><code>/^[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
我不知道我做错了什么以及如何解决这个问题...我在这里缺少什么?
您的正则表达式在某些地方 "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]+)*$/
其中UPPER
和lower
是大小写字母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()
方法中使用它,请删除 ^
和 $
,因为它们在那里是多余的。