你做得很好。您需要在第一个字符类中添加连字符和点。注意:使用连字符,因为它代表字符类中的范围,所以您需要将它定位在上下文中它不能指定范围的位置 - 并不是说将它放在看起来可能是无效范围的位置,例如,@987654321 @,但 positionally 不能是范围,即第一个或最后一个。所以你的第一个字符类看起来像这样:
[a-zA-Z 0-9.-]{1,5} 或 [-a-zA-Z0-9 .]{1,5}
所以,我们刚刚定义了一个细分的样子。该模式可以重复出现零次或多次。当然,有很多方法可以做到这一点,但我更喜欢正则表达式子例程,因为这允许代码重用。现在,如果规格发生变化,或者您正在测试并意识到您必须调整该段模式,您只需在一个地方进行更改。
BRE 或 ERE 不支持子例程,但大多数广泛使用的现代正则表达式引擎都支持它们(Perl、PCRE、Ruby、Delphi、R、PHP)。它们非常简单使用和理解。基本上,您只需要能够引用它(听起来很熟悉?引用返回?反向引用?),所以这意味着我们需要捕获我们希望重复的正则表达式。那么它就像引用它一样简单,但不是引用捕获的值(数据)的\1,我们希望将其称为(?1),捕获表达式。为此,我们在逻辑上定义了一个子例程:
([a-zA-Z 0-9.-]{1,5})(,(?1))*
所以,第一组基本上定义了我们的子程序,第二组由一个逗号组成,后跟我们用于第一组的相同段定义表达式,即 可选 ('*'是零个或多个量词)。
如果您在考虑效率的情况下对大量数据进行操作,请不要在不必要时进行捕获。如果您使用括号的唯一目的是交替(例如,\b[bB](asset|eagle)\b hound)或量化,如在我们的第二组中,请使用(?: ... ) 表示法,这向正则表达式引擎表示这是一个非捕获组。无需详细说明,维护匹配位置会产生大量开销——并不是说它本身很复杂,只是可能高度重复。正则表达式引擎将匹配、存储信息,然后当匹配失败时,它们“放弃”匹配并从下一个匹配的子字符串开始重试。每次它们与您的捕获组匹配时,它们都会再次存储该信息。好的,我现在离开肥皂盒了。 :-)
所以,我们快到了。我说“几乎”是因为我没有所有信息。但是如果这应该是“主题”(行、字段等——您正在评估的数据样本)的唯一占用者,您应该将其锚定为“断言”该要求。插入符号 '^' 是主题的开头,美元 '$' 是主题的结尾,因此通过将我们的表达式封装在 ^ ... $ 中,我们断言主题完全匹配,前面 -背靠背。这些断言的长度为零;他们不消耗任何数据,只声明一个相对位置。您可以对它们进行操作,例如,s/^/ / 会将整个文档缩进两个空格。您并没有真正用两个空格替换行的开头,但是您可以在那个虚构的零长度位置上进行操作。 (对零长度断言 [又名零宽度断言,或环视] 进行一些研究,以发现现代正则表达式的强大功能。例如,在之前的正则表达式中,如果我想确保我没有在空行:s/^(?!$)/ /)
另外,您没有说是否需要捕获结果以对其进行处理。我的印象是它只是验证,所以没有必要。但是,如果需要,您可以将整个表达式包装在捕获括号中:^( ... )$。
我将提供一个最终解决方案,不假设您需要捕获但确实假设整个主题应包含以下值:
^([a-zA-Z 0-9. -]{1,5})(?:,(?1))*$
我知道我讲了一点,但你说你是正则表达式的新手,所以想提供一些细节。希望不要太详细。
顺便说一句,一个很好的教程资源是正则表达式点信息,一个很棒的正则表达式开发和测试工具是 regex101 dot com。关于堆栈溢出,我永远也说不完!