【问题标题】:Regex- Validation (validate string with not more than 1 space in between)正则表达式验证(验证字符串之间不超过 1 个空格)
【发布时间】:2022-01-20 14:13:10
【问题描述】:

我正在寻找一种解决方案,可以匹配没有 2 个或更多空格的字符串。 我已经检查了多个答案,他们给出了字符串有多个空格的字符串,但我想要相反的,比如(abc bb) 是我的匹配字符串不是(abc bb or abc bb etc)

这是我的验证码

/^([A-Za-z0-9\_\- ]+){5,255}$/

我正在检查的内容 长度应为 5 到 255 个字符,并且只能包含字母、数字、-(连字符)、_(下划线)或空格。

** 中间没有多个空格的字符串不应该是有效匹配。

abc bb => match
abcd  => not match (only 4 characters)
abc d => match
   bbv => not match (only 3 characters)
b b v => match
abc  bb => not match
abc   bb => not match
abc    bb => not match
There is  a   very good question => Not match
There is a very good question => match
The thing  might  not   go   your way => not match
The thing might not go your way => match

Thanks

【问题讨论】:

  • 所有示例字符串都有 1 或 2 个单词。您的项目数据实际上可能在字符串中包含 3 个或更多单词吗?充分展示项目数据的可变性非常重要,以便贡献者能够最好地回答您的问题。请澄清您的minimal reproducible example
  • 只包含空格的 255 个字符的字符串是否匹配?是否要求至少有一个可见字符?
  • @mickmackusa 是的,这是真的,我添加了更多示例。感谢您的宝贵建议。

标签: php regex


【解决方案1】:

在更新问题后编辑:

您可以先声明允许的格式,其间最多只能有一个空格,然后匹配 5-255 个字符,后跟可选空格。

^ *+(?=[\w-]++(?> ?[\w-]+)*+ *$)[\w -]{4,254}[\w-] *$

模式匹配:

  • ^ 字符串开始
  • *+ 使用所有格量词匹配可选空格(不要回溯)
  • (?= 正向前瞻,断言右边是
    • [\w-]++ 匹配 1+ 个单词字符或 -
    • (?> ?[\w-]+)*+ 重复匹配一个可选空格,然后在一个原子组中出现 1 次以上的 \w-
    • *$ 匹配可选空格直到字符串结束
  • )关闭前瞻
  • [\w -]{4,254}[\w-] 匹配 4 到 254 次出现的 \w -
  • * 匹配可选空格
  • $字符串结束

Regex demo

示例代码

$strings = [
    "abc bb",
    "abc d",
    "b b v",
    "There is a very good question",
    "The thing might not go your way",
    "abcd",
    "   bbv",
    "abc  bb",
    "abc   bb",
    "abc    bb",
    "There is  a   very good question",
    "The thing  might  not   go   your way"
];

$pattern = "/^ *+(?=[\w-]++(?> ?[\w-]+)*+ *$)[\w -]{4,254}[\w-] *$/";

foreach ($strings as $s) {
    if (preg_match($pattern, $s)) {
        echo "Match for: [$s]" . PHP_EOL;
    } else {
        echo "No match for: [$s]" . PHP_EOL;
    }
}

输出

Match for: [abc bb]
Match for: [abc d]
Match for: [b b v]
Match for: [There is a very good question]
Match for: [The thing might not go your way]
No match for: [abcd]
No match for: [   bbv]
No match for: [abc  bb]
No match for: [abc   bb]
No match for: [abc    bb]
No match for: [There is  a   very good question]
No match for: [The thing  might  not   go   your way]

【讨论】:

  • 由于允许尾随空格,您甚至可以将其缩短为^(?=.{5,255}$) *(?>[\w-]+ ?)+ *$
  • @CasimiretHippolyte 这是一个带有原子团的漂亮模式:-)
  • @Thefourthbird ,感谢您的精彩解释,对不起我的错误,这 2 个(匹配:[abcd] 匹配:[bbv])不应匹配,因为前导和尾随空格不应匹配算作字符。
  • @rkrathor 你在评估之前对trim()ing 你的价值观不感兴趣吗?
  • 非常感谢@Thefourthbird 的快速响应和帮助。
【解决方案2】:

编辑的答案,编辑后的问题。你可以试试:

^ *+(?!.+?  \S)[\w -]{4,254}[\w-] *$

在线查看demo


  • ^ *+ - 起始线锚点后跟 0+(占有,不回馈)空格;
  • (?!.+? \S) - 负前瞻,以防止任何行在非空白字符之间有两个空格字符;
  • [\w -]{4,254}[\w-] - 在最后一个连字符/单词字符之前匹配任何单词字符、连字符或空格 4-254 次;
  • *$ - 结束线锚点前有 0+ 个(贪婪)空格。

【讨论】:

  • 抱歉,不,这是个坏主意,它不适用于用字母分隔的两个空格。
  • @CasimiretHippolyte,不用担心。整个问题刚刚改变,所以答案也改变了。
  • 那是一个很好的space *+我有点借了它:-)
【解决方案3】:

好的,我将提供一个模式,它将忽略前导和尾随空格,遵守可挽救的字符串长度,并确保可挽救的字符串中不存在多个空格。

但首先,让我们通过将 255 减少到 10 来简化您的长度要求……只是为了单元测试。在我的回答中,假设我验证的字符串长度在 5 到 10 个字符之间(而不是 5 到 255)。

我建议的模式将允许前导空格,匹配第一个单词或破折号字符,然后匹配任何字符 3 到 8,然后是最后一个单词或破折号字符,然后允许尾随空格。 1+3+1 给出最少 5 个字符,1+8+1 给出最多 10 个字符。对于提出的问题,使用 1+3+1 和 1+253+1 求和所需的长度限制:{5,255}

^ *             #match start of string then zero or more allowable/uncountable spaces
[\w-]           #match first word-or-dash character
(?=             #lookahead
   .{3,8}       #match to any character 3 to 8 times to enforce length requirements
   [\w-]        #match last word-or-dash character
    *$          #match allowable/uncountable trailing spaces then end of string
) ?             #close lookahead, then match zero or one space
(?>[\w-]+ ?)+   #repeatedly match one or more word-or-dash sequences followed by zero or one space
 *$             #match zero or more spaces until the end of the string

代码:(Demo)

$tests = [
    '123 56',
    ' 1234',
    '1234 ',
    '123 5',
    '   1234',
    '    1234    ',
    ' 1 3 5 7 9 ',
    '  1 3 5 7 9   ',
    '   12 45 78 01',
    '   12 45 78 0 ',
    '  1234567890  ',
    ' 12345678901 ',
    '1 3 5 7 9  ',
    '1 3 5 7 9 1',
    '1 3 5 7 9 ',
    '1 3  6 8',
];

foreach ($tests as $test) {
    printf(
        "'%s' => %s or %s\n",
        $test,
        preg_match('/^ *[\w-](?=.{3,8}[\w-] *$) ?(?>[\w-]+ ?)+ *$/', $test) ? 'pass' : 'fail',
        preg_match('/^(?=.{5,10}$)(?>[\w-]+ ?)+$/', trim($test)) ? 'pass' : 'fail'
    );
}

输出:

'123 56' => pass or pass
' 1234' => fail or fail
'1234 ' => fail or fail
'123 5' => pass or pass
'   1234' => fail or fail
'    1234    ' => fail or fail
' 1 3 5 7 9 ' => pass or pass
'  1 3 5 7 9   ' => pass or pass
'   12 45 78 01' => fail or fail
'   12 45 78 0 ' => pass or pass
'  1234567890  ' => pass or pass
' 12345678901 ' => fail or fail
'1 3 5 7 9  ' => pass or pass
'1 3 5 7 9 1' => fail or fail
'1 3 5 7 9 ' => pass or pass
'1 3  6 8' => fail or fail

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 2013-08-04
    • 1970-01-01
    相关资源
    最近更新 更多