验证字符串以仅包含限定字符和中间的特定可选子字符串

Posted

技术标签:

【中文标题】验证字符串以仅包含限定字符和中间的特定可选子字符串【英文标题】:Validate string to contain only qualifying characters and a specific optional substring in the middle 【发布时间】:2021-10-28 08:26:02 【问题描述】:

我正在尝试在 php 中创建一个正则表达式。我可以让它用其他语言工作,但不能用 PHP。

我想验证数组中的项目名称

它们可以包含大小写字母、数字、下划线和连字符。 它们可以包含 => 作为精确字符串,而不是单独的字符。 不能以=>开头。 他们无法以=> 结束。

我当前的代码:

$regex = '/^[a-zA-Z0-9-_]+$/';    // contains A-Z a-z 0-9 - _
//$regex = '([^=>]$)';  // doesn't end with =>
//$regex = '~.=>~';  // doesn't start  with =>

if (preg_match($regex, 'Field_name_true2')) 
    echo 'true';
 else 
    echo 'false';
;
// Field=>Value-True
// =>False_name
//Bad_name_2=>

【问题讨论】:

你说你可以让它在其他语言中工作——你能举一个例子吗? @Shane 你能给我们展示一组真实的字符串,它们代表将遇到的正常和边缘情况吗?你的例子都包含=>。这是实际上的要求吗?你最终会解析键值表达式吗?你能控制这种格式吗?为什么这些数据是这种格式的? 【参考方案1】:

对于示例数据,您可以使用

^[a-zA-Z0-9_-]+=>[a-zA-Z0-9_-]+$

模式匹配:

^ 字符串开始 [a-zA-Z0-9_-]+ 匹配任何列出的范围或字符的 1 次以上(不能以 => 开头) => 字面匹配 [a-zA-Z0-9_-]+ 再次匹配任何列出的范围或字符的 1 次以上 $字符串结束

Regex demo

如果你想允许可选空格:

^\h*[a-zA-Z0-9_-]+\h*=>\h*[a-zA-Z0-9_-]+\h*$

Regex demo

注意[a-zA-Z0-9_-]可以写成[\w-]

【讨论】:

此外,some=>thing=>else 与您的方法不匹配(不知道是否应该以及是否真的值得努力......) 我需要 OP 更清楚地说明,但这与 foo_bar 不匹配,根据要求的英文表达应该符合条件。 @mickmackusa 最初我想发布您发布的内容,但我在 cmets 中只看到了 3 个包含 => 的示例,所以我强制匹配。【参考方案2】:

这里绝对不需要环视。

锚点和可选组就足够了。

Demo

/^[\w-]+(?:=>[\w-]+)?$/
        ^^^^^^^^^^^^^-- this whole non-capturing group is optional

这允许完全由 [0-9a-zA-Z-] 组成的完整字符串或由 => 拆分 ONCE。

非捕获组可能出现零次或一次。

换句话说,=> 可能出现在一个或多个 [\w-] 字符之后,但如果确实出现,则必须紧跟一个或多个 [\w-] 字符,直到字符串结尾。


为了涵盖问题要求中的一些歧义:

如果foo=>bar=>bam 有效,则使用/^[\w-]+(?:=>[\w-]+)*$/?(零或一)替换为*(零或更多)。

如果foo=>=>bar 有效,则使用/^[\w-]+(?:(?:=>)+[\w-]+)*$/=>(必须出现一次)替换为(?:=>)+(子字符串必须出现一次或多次)。

【讨论】:

/^[\w-]+(?:=>[\w-]+)*$/ 是正确的 - 感谢您期待未提出的问题。 感谢您的宝贵时间。谢谢。 @Shane 我注意到您从未接受过 Stack Overflow 上的答案。请阅读:meta.stackexchange.com/q/5234/352329【参考方案3】:

使用消极的环顾四周。 Negative lookahead (?!=>)开头禁止以=>开头,负lookbehind(?<!=>)结尾禁止以=>结尾。

^(?!=>)(?:[a-zA-Z0-9-_]+(=>)?)+(?<!=>)$

DEMO

【讨论】:

谢谢 - 你的模式奏效了。我很感激你的时间。我正把头撞到墙上,试图整理最后一点。【参考方案4】:

嗯,你的字符范围等于\w,所以你可以使用

^(?!=>)(?:(?!=>$)(?:[-\w]|=>))+$

此构造使用“经过调和的贪婪令牌”,请参阅a demo on regex101.com


更闪亮,更复杂,肯定是最重要的,你可以使用子例程:

(?(DEFINE)
    (?<chars>[-\w])             # equals to A-Z, a-z, 0-9, _, -
    (?<af>=>)                   # "arrow function"
    (?<item>
        (?!(?&af))              # no af at the beginning
        (?:(?&af)?(?&chars)++)+
        (?!(?&af))              # no af at the end
    )
)
^(?&item)$

another demo on regex101.com

【讨论】:

以上是关于验证字符串以仅包含限定字符和中间的特定可选子字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何键入 Typescript 数组以仅接受一组特定的值?

验证以仅在后跟字母时允许空格字符

使用 awk 或 perl 从 CSV 中提取特定列(解析)

Json - 可选子文档

Educational Codeforces Round 110 (Rated for Div. 2) - C. Unstable String - DP

Powershell仅在包含特定字符串的文件夹名称中移动子目录中的项目