【问题标题】:Regex to match a-z spaces, character limit, only first letter capitalized正则表达式匹配 a-z 空格,字符限制,仅首字母大写
【发布时间】:2013-07-06 08:36:44
【问题描述】:

我需要一些关于正则表达式的帮助。这点我很糟糕。

规则:

  • 仅限字母 a 到 z 和空格
  • 最少 2 个字母
  • 最多 30 个字母
  • 每个单词必须至少包含 2 个字母
  • 只有每个单词的第一个字母可以为大写,但第一个字母必须始终为大写

我的尝试:

^[A-Z][a-z]{2,30}$

我在 PHP 中使用它。

【问题讨论】:

  • This should get you started. 但更重要的是:您在哪种语言/工具中使用此正则表达式?
  • 前三个规则完全在正则表达式的能力范围内。但是,如果您尝试对所有四个规则使用单个正则表达式,第四条规则将是一个挑战。
  • @nickb 单独的第四个也不是问题,并且正交要求可以与前瞻如果风味提供它们相结合。因此,我对 OP 的问题
  • 我并不经常被否决......显然,我误解了一些东西。你能澄清一下你的第四个要求是什么意思吗?
  • @pete 我的意思是“我的名字是鲍勃”会匹配,而“我的名字是鲍勃”不会

标签: php regex


【解决方案1】:

好的,让我们先尝试解决要求 1 到 3。如果您的意思是 2 到 30 个字符,就这么简单:

^[a-zA-Z ]{2,30}$

现在是其他要求。让我们独自处理这些。第 4 点要求每个单词的格式为[a-zA-Z][a-z]*。为了确保每个单词至少有两个字母,我们可以简单地将* 变成+(这意味着1 次或多次重复)。如果我们在它们周围插入显式空格,则可以确保[a-z]+ 不能直接跟大写字母:

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

请注意,我将第一个单词分开处理。

最后,我们如何将两者结合起来?通过将一个放入lookahead。我要在这里数数:

^(?=[a-zA-Z ]{2,30}$)[A-Z][a-z]+(?:[ ]+[a-zA-Z][a-z]+)*$

这是可行的,因为在根据前瞻检查输入后,引擎会将其“光标”重置到它开始的位置(字符串的开头)并照常继续匹配。这样我们就可以在输入上运行两次,检查独立的条件。

最后,请注意,前瞻要求仅转换为字符串的长度。在这种情况下,单独检查会更容易(而且通常更好):

$len = strlen($input)
if ($len < 2 || $len > 30)
    // report error about string length
else if (!preg_match('/^[A-Z][a-z]+(?:[ ]+[a-zA-Z][a-z]+)*$/', $input))
    // report error about pattern
else
    // process input

这使得根据违反的条件提供合理的错误消息变得更加容易。

【讨论】:

  • 太棒了,简直太棒了。你知道你的正则表达式。多谢!真的
  • @PopeyeDoyle :) 试试我在对您的问题的第一条评论中链接的教程。到周末结束时,你会自己想出这样的模式。
【解决方案2】:

让我们试试这个:

^[A-Z]((?<= )[A-Z]|[a-z ]){2,29}$

[A-Z]          -- a capital letter
(
  (?<= )[A-Z]  -- either a capital letter preceded by a space
  |            -- or 
  [a-z ]       -- a lowercase letter or a space
){2,29}  -- 2 to 29 times (plus the initial capital)

您需要使用 PCRE(而不是 ereg_*)才能使后视工作。

"My name Is bob"
   ↑  ↑  ↑
   |  |  \-- this is a "(?<= )[A-Z]"
   |  \--- this is a "[a-z]"
   \---- this is a "[ ]"


"naMe"
   ↑
   \-- this is NOT a "(?<= )[A-Z]" (a character before the [A-Z] is not a space)

编辑:该死,您添加了“每个单词必须至少有 2 个字母”。使用m.buettner's。

【讨论】:

  • 30 必须是 29 否则您将允许 31 个字符的字符串。
  • 你可以修复你的两个字母要求:^[A-Z][a-z]((?&lt;=[ ])[A-Z]|[a-z]|[ ](?=[A-Za-z]{2})){2,29}$ 或类似的东西;)
  • 不,在这一点上,我认为使用正则表达式并不明智。我会匹配^[A-Z][a-z]+( [A-Za-z][a-z]+)*$ 并单独检查长度。
  • @PavelAnossov 是的,只要你没有某种框架就更好了,你所能做的就是提供一个单一的验证正则表达式(这里可能不是这种情况)跨度>
猜你喜欢
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 2011-04-06
相关资源
最近更新 更多