【问题标题】:Regex to match alphanumeric characters, underscore, periods and dash, allowing dot and dash only in the middle正则表达式匹配字母数字字符、下划线、句点和破折号,仅在中间允许点和破折号
【发布时间】:2012-05-26 06:58:12
【问题描述】:

目前,我正在使用这个:

if (preg_match ('/^[a-zA-Z0-9_]+([a-zA-Z0-9_]*[.-]?[a-zA-Z0-9_]*)*[a-zA-Z0-9_]+$/', $product) ) {
return true;
} else { 
return false
}

比如我要匹配:

  1. pro.duct-name_
  2. _pro.duct.name
  3. p.r.o.d_u_c_t.n-a-m-e

但我不想匹配:

  1. pro..ductname
  2. .productname-
  3. -productname.
  4. -productname

【问题讨论】:

  • 编辑了示例,使其更易于理解。是否需要进一步解释。请让我知道,我很乐意进一步澄清。
  • 为什么pro..ductname 不应该匹配?点在中间?
  • 如果dot 不会出现两次或任何字符?
  • 因为,我不想连续匹配两次dotdashDotdash 可以在中间出现多次,但不能连续出现。现在,如果dotdash 一个接一个出现会怎样?我们允许product.-name
  • 问:“如果只有dot 不会出现两次或任何字符?” A:Dotdash 不会出现两次,任何其他字母数字字符都可以出现两次,ppppppppp 应该匹配。

标签: php regex preg-match


【解决方案1】:

答案是

/^[a-zA-Z0-9_]+([-.][a-zA-Z0-9_]+)*$/

如果您允许包含 .--. 的字符串不匹配。无论如何,您为什么要允许它们匹配?但是如果你真的需要这些字符串来匹配,一个可能的解决方案是

/^[a-zA-Z0-9_]+((\.(-\.)*-?|-(\.-)*\.?)[a-zA-Z0-9_]+)*$/

第一个正则表达式的单个.- 被替换为交替的.- 序列,以.- 开头,可选地后跟-. 或@分别为 987654334@ 对,可选地后跟 -.,以允许偶数个交替字符。这种复杂性可能是过冲,但似乎是当前规范所需要的。如果最多需要 2 个交替 .-,则正则表达式变为

/^[a-zA-Z0-9_]+((\.-?|-\.?)[a-zA-Z0-9_]+)*$/

测试herehere

【讨论】:

  • 第二个确实有效。非常感谢,虽然我必须承认,我不完全理解你的第二个正则表达式的顺序。
  • 而且,我喜欢这个位 - 正则表达式中的 (\.-?|-\.?)[a-zA-Z0-9_]+。这样就解决了问题。很好的逻辑。
  • :-) 谢谢。考虑到您刚刚写的内容,我添加了最后一个正则表达式
【解决方案2】:

试试这个

(?im)^([a-z_][\w\.\-]+)(?![\.\-])\b

更新 1

(?im)^([a-z_](?:[\.\-]\w|\w)+(?![\.\-]))$

更新 2

(?im)^([a-z_](?:\.\-\w|\-\.\w|\-\w|\.\w|\w)+)$

说明

<!--
(?im)^([a-z_](?:\.\-\w|\-\.\w|\-\w|\.\w|\w)+)$

Match the remainder of the regex with the options: case insensitive (i); ^ and $ match at line breaks (m) «(?im)»
Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
Match the regular expression below and capture its match into backreference number 1 «([a-z_](?:\.\-\w|\-\.\w|\-\w|\.\w|\w)+)»
   Match a single character present in the list below «[a-z_]»
      A character in the range between “a” and “z” «a-z»
      The character “_” «_»
   Match the regular expression below «(?:\.\-\w|\-\.\w|\-\w|\.\w|\w)+»
      Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
      Match either the regular expression below (attempting the next alternative only if this one fails) «\.\-\w»
         Match the character “.” literally «\.»
         Match the character “-” literally «\-»
         Match a single character that is a “word character” (letters, digits, and underscores) «\w»
      Or match regular expression number 2 below (attempting the next alternative only if this one fails) «\-\.\w»
         Match the character “-” literally «\-»
         Match the character “.” literally «\.»
         Match a single character that is a “word character” (letters, digits, and underscores) «\w»
      Or match regular expression number 3 below (attempting the next alternative only if this one fails) «\-\w»
         Match the character “-” literally «\-»
         Match a single character that is a “word character” (letters, digits, and underscores) «\w»
      Or match regular expression number 4 below (attempting the next alternative only if this one fails) «\.\w»
         Match the character “.” literally «\.»
         Match a single character that is a “word character” (letters, digits, and underscores) «\w»
      Or match regular expression number 5 below (the entire group fails if this one fails to match) «\w»
         Match a single character that is a “word character” (letters, digits, and underscores) «\w»
Assert position at the end of a line (at the end of the string or before a line break character) «$»
-->

你可以测试它here

【讨论】:

  • \w 与 [a-zA-Z0-9_] 不同
  • 我不知道这是否是@Walter 所指的,但要详细说明一下,the PHP manual 说:“单词”字符是任何字母、数字或下划线字符,即可以成为 Perl“单词”一部分的任何字符。字母和数字的定义由 PCRE 的字符表控制,并且如果发生特定于语言环境的匹配,可能会有所不同。例如,在“fr”(法语)语言环境中,一些大于 128 的字符代码用于重音字母,这些字符由 \w 匹配。
  • @WalterTross:您能否提供一个不起作用的示例,因为该测试适用于 OP 的示例数据。
  • product.-name 必须匹配(请参阅 OP 的 cmets),但不匹配。鉴于 OP 的第一个正则表达式,123product 也应该匹配。 (?![\.\-]) 部分是不需要的,因为它隐含在它前面的内容中。 [\.\-] 更易读为 [-.]
  • @WalterTross:感谢您指出这一点。请参阅我的更新 2。确实不需要额外的negetive lookahead。如果123product 产品必须匹配,那么模式会更简单,只需将第一个character class 替换为\w。 OP 从未对此发表评论。
【解决方案3】:

应该这样做:

/^[A-z0-9_]([.-]?[A-Z0-9_]+)*[.-]?[A-z0-9_]$/

它将确保单词以字母数字或下划线字符开头和结尾。 中间的括号将确保一行中最多有一个句点或破折号,后跟至少一个字母数字或下划线字符。

【讨论】:

    【解决方案4】:
    /^[A-Z0-9_][A-Z0-9_.-]*[A-Z0-9_]$/i
    

    这确保第一个和最后一个字符不是破折号或句点;中间的其余部分可以由任何字符组成(在您选择的集合中)。

    【讨论】:

      【解决方案5】:

      下面的正则表达式将检查任何包含字符、数字、破折号等的字符串,并且中间只有一个点。

      /^[A-Za-z0-9_-]+(\.){1}[A-Za-z0-9_-]+$/i
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-13
        • 1970-01-01
        • 2016-09-07
        相关资源
        最近更新 更多