代码之家  ›  专栏  ›  技术社区  ›  William Rosenbloom

如何指定regex应至少包含一个可选组?[副本]

  •  0
  • William Rosenbloom  · 技术社区  · 6 年前

    我需要一个正则表达式来验证 ISO 8601 duration format (除了我不需要的部分)。

    PNynmndnhnmns公司

    PNW

    以下是我的资料:

    ^P(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$
    

    唯一的问题是字符串 P PT 允许使用此regex,因为所有部分都是“零或一” ? .

    • 必须至少有一个组件(日期或时间)
    • 如果有 T 然后需要一个时间分量(h、m或s)
    • 如果有 T 那么可能有或没有任何日期成分(Y、M或D)
    • 允许溢出(例如 P72H 主要相当于 P3D )

    可接受输入:

    P1Y        // date component only
    P2MT30M    // date and time components
    PT6H       // time component only
    P5W        // another date component
    

    不可接受的输入:

    P         // no components
    PT        // no components
    P3MT      // T specified but not time components
    

    现在,无效的字符串正在通过客户端验证,但在服务器端失败,因为它被传递到 DateInteval 但如果可能的话,我希望在客户方面失败。如果每个人都使用Chrome40+我可以指定 minlength='3' 对输入元素有帮助,但不幸的是事实并非如此。

    0 回复  |  直到 6 年前
        1
  •  18
  •   Wiktor Stribiżew    6 年前

    如果你几乎所有的部分都是可选的,但是你想确保之后还有其他的东西 P T ,您可以使用look a heads:

    ^P(?=\d+[YMWD])(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
      ^^^^^^^^^^^^                               ^^^^^^^^^^^^
    

    它们需要一个数字序列,后跟指定集合中的一个字母,以便在前面的模式之后立即显示。

    demo

    更新

    如果 可以为“空”,使用

    ^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
    

    another demo . 在这里, (?!$) 确保字符串不等于 右边一定还有其他符号。

    或者,正如@ulugbekumirov所建议的那样, enough to just use T(?=\d) (因为所有可选部件都以数字开头):

    ^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$
    

    更新2

    如果数字既可以是浮点数也可以是整数,则加上 (?:\.\d+)? 每次之后 \d+ . 以下是更新1中的更新模式:

    ^P(?!$)(\d+(?:\.\d+)?Y)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?W)?(\d+(?:\.\d+)?D)?(T(?=\d)(\d+(?:\.\d+)?H)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?S)?)?$
    
        2
  •  3
  •   Rafi    6 年前

    以上答案不包括小数的情况(参见 here 详细信息)。小数部分可以出现在最后一个元素上。以下regex包含小数部分:

    ^P(?!$)((\d+Y)|(\d+\.\d+Y$))?((\d+M)|(\d+\.\d+M$))?((\d+W)|(\d+\.\d+W$))?((\d+D)|(\d+\.\d+D$))?(T(?=\d)((\d+H)|(\d+\.\d+H$))?((\d+M)|(\d+\.\d+M$))?(\d+(\.\d+)?S)?)??$
    

    here 用于测试。