仅接受字母和空格的正则表达式,不允许字符串开头和结尾有空格。

8
我对验证输入字段有以下要求:
  1. 它只能包含字母和字母之间的空格。
  2. 字符串开头或结尾不能包含空格。
  3. 它不能包含任何其他特殊字符。
我使用以下正则表达式进行验证:
^(?!\s*$)[-a-zA-Z ]*$

但是这允许在开头有空格。非常感谢您的帮助。

1
请在此网站上尝试在线操作。 - Crazenezz
5个回答

8

如果您使用String.matches方法,这应该可以正常工作。我假设您想要英文字母。

"[a-zA-Z]+(\\s+[a-zA-Z]+)*"

请注意,\s 将允许所有类型的空格字符。 在Java中,它相当于
[ \t\n\x0B\f\r]

其中包括水平制表符(09)、换行符(10)、回车符(13)、换页符(12)、退格符(08)、空格(32)。

如果您只想允许空格(32):

"[a-zA-Z]+( +[a-zA-Z]+)*"

您可以通过将捕获组( +[a-zA-Z]+)更改为非捕获组来进一步优化上面的正则表达式(使用String.matches您无法单独获取单词)。也可以更改量词使它们成为贪婪的,因为在这里回溯没有意义。
"[a-zA-Z]++(?: ++[a-zA-Z]++)*+"

3
如果您正在使用Java的matches()方法,那么这个正则表达式是正确的,但我仍然建议您锚定它:^([a-zA-Z]+\s+)*[a-zA-Z]+$ - Alan Moore
是的。我假设使用matches()方法。谢谢澄清。+1。 - nhahtdh

8

对我来说,唯一合乎逻辑的方法是:

^\p{L}+(?: \p{L}+)*$

字符串开头必须至少有一个字母。(我用字母的Unicode代码属性\p{L}替换了您的[a-zA-Z])。然后可以有一个空格,后面至少跟着一个字母,这部分可以重复。

\p{L}:任何语言的任何类型的字母。请参见regular-expressions.info

你表达式中的问题^(?!\s*$)是,如果只有空格直到字符串结尾,前瞻就会失败。如果你想禁止前导空格,只需在前瞻中去除字符串结束锚点==>^(?!\s)[-a-zA-Z ]*$。但这仍然允许字符串以空格结尾。为了避免这种情况,请在字符串末尾回溯^(?!\s)[-a-zA-Z ]*(?<!\s)$。但我认为这个任务不需要使用环视。


1

试试这个:

^(((?<!^)\s(?!$)|[-a-zA-Z])*)$

这个表达式使用 负向前瞻负向后顾 来禁止字符串开头或结尾的空格,并要求匹配整个字符串。


你的正则表达式有误,请再次检查括号。 - Crazenezz
@Crazenezz 谢谢,末尾缺少一个 ) - Sergey Kalinichenko
不需要太花哨。正如其他三位回答者(到目前为止)所展示的那样,这是一个情况,在这种情况下,正确匹配您想要的内容就足以过滤掉您不想要的内容。 - Alan Moore
@AlanMoore 你说的“花哨”是什么?现在回顾环视已经很普遍了。一个表达式“匹配一个字母或空格,但不在输入的开头或结尾”很容易理解,而且是唯一不重复字符类[-A-Za-z]的解决方案。只是语法让它看起来很复杂,但本质上它很简单。 - Sergey Kalinichenko
2
我的意思是,为什么要使用复杂的语法,当简单的语法至少同样有效呢?一旦你知道这些符号的含义,不仅^[a-zA-Z]+(\s+[a-zA-Z]+)*$完全匹配所需的内容,而且它尽可能高效地完成了匹配。根据RegexBuddy的说法,这个正则表达式只需要22步就可以匹配字符串“Lorem ipsum tritani impedit civibus ei pri”,而你的正则表达式需要222步! - Alan Moore

1

我认为问题在于在空格的否定之前有一个问号,这意味着它是可选的。

这应该可以工作:

[a-zA-Z]{1}([a-zA-Z\s]*[a-zA-Z]{1})?

至少一个字母序列,然后是可选的带空格的字符串,但总是以字母结尾


不,(?!\s*$)是一个负向先行断言; 它断言从当前位置(由于前面的 ^,它是字符串的开头)开始,不能匹配零个或多个空格字符,后跟字符串的结尾。那是不正确的,但不是你提出的原因。你的正则表达式将起作用,但你应该去掉 {1} (它没有任何效果)并添加锚点。如果你碰巧使用Java的 matches() 方法,锚点是可选的,但它们有助于传达你的意图,并使将正则表达式移植到其他语言更容易。 - Alan Moore

1

我不知道你接受的字符串中的单词是否可以用超过一个空格分隔。如果可以:

^[a-zA-Z]+(( )+[a-zA-z]+)*$

如果不能:

^[a-zA-Z]+( [a-zA-z]+)*$

字符串必须以字母(或几个字母)开头,不能有空格。

字符串可以包含几个单词,但除第一个单词外,每个单词前必须有空格。

希望我能帮到你。


OP问道:“它不能包含字符串开头或结尾的空格。如果示例如下:<space><string><space><string><space>,则结果将为<string><space><string>。您的正则表达式只能解决这个问题<string><space><string>,如果用户输入像我之前的示例那样的问题,则您的正则表达式无法解决。” - Crazenezz
我不同意。 OP 要求正则表达式来“验证输入字段”。因此,对于类似<空格> <字符串> <空格> <字符串> <空格>这样的数据,匹配应返回 false,这就是我的正则表达式的工作原理。 - Pshemo
在我仔细再次阅读后,也许我的思路出了问题。我的想法是,如果有一个像上面的例子那样的字符串,它将检查并删除填充字符串前后的空格,并显示结果(不知道 OP 是否希望即使用户输入错误,如 <space>Hello World<space> 也能捕获)。 - Crazenezz
我会再次投票,但需要2小时才能再次投票。希望这不会引起不快 :-) - Crazenezz

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