我正在为LMS构建SCORM 2004 javascript API,SCORM 2004要求之一是传递给它的时间间隔必须遵循以下格式。有谁知道这个正则表达式是什么?我试图围绕它,但无济于事。注意:P必须始终是第一个字符。
P [YY] [MM] [日] [T [HH] [nm]的[S [.S] S]] 其中:
- y:年数(整数,> = 0,不受限制)
- m:月数(整数,> = 0,不受限制)
- d:天数(整数,> = 0,不受限制)
- h:小时数(整数,> = 0,不受限制)
- n:分钟数(整数,> = 0,不受限制)
- s:秒数或秒数的分数(实数或整数,> = 0,不是 限制)。如果使用几分之一秒,则SCORM会进一步将字符串限制为 最多2位数(例如34.45 - 有效,34.45454545 - 无效)。
- 如果是,则出现字符文字指示符P,Y,M,D,T,H,M和S. 存在相应的非零值。
- 应支持零填充值。零填充不会改变 由一组字符表示的数字的整数值。对于 例如,PT05H相当于PT5H和PT000005H。
示例 -
- P1Y3M2DT3H表示1年,3个月,2天和3的时间段 小时
- PT3H5M表示3小时5分钟的时间段
非常感谢任何帮助。
谢谢!
更新
我添加了一些必须保留的额外标准 -
- 指示符P应存在
- 如果是年,月,日,小时,分钟或秒的值 零,值和对应 字符文字指定可能是 省略,但至少有一个字符 字面指示符和值应该是 除指定人外还有礼物 P
- 如果所有时间成分(小时, 不使用分钟和秒钟。一个 零值可以与任何一个一起使用 时间成分(例如,PT0S)
答案 0 :(得分:5)
这是我使用的正则表达式;
^P(?=\w*\d)(?:\d+Y|Y)?(?:\d+M|M)?(?:\d+D|D)?(?:T(?:\d+H|H)?(?:\d+M|M)?(?:\d+(?:\.\d{1,2})?S|S)?)?$
答案 1 :(得分:1)
使用[0-9]
匹配任何数字。 +
匹配一次或多次重复。 ?
匹配0或1次重复。 ()
分组并提取输出。
P(([0-9]+Y)?([0-9]+M)?([0-9]+D)?)(T([0-9]+H)?([0-9]+M)?([0-9.]+S)?)?
import re
>>> p = re.compile('P(([0-9]+Y)?([0-9]+M)?([0-9]+D)?)(T([0-9]+H)?([0-9]+M)?([0-9.]+S)?)?')
>>> p.match('P1Y3M2DT3H').groups()
('1Y3M2D', '1Y', '3M', '2D', 'T3H', '3H', None, None)
>>> p.match('P3M2DT3H').groups()
('3M2D', None, '3M', '2D', 'T3H', '3H', None, None)
>>> p.match('PT3H5M').groups()
('', None, None, None, 'T3H5M', '3H', '5M', None)
>>> p.match('P1Y3M4D').groups()
('1Y3M4D', '1Y', '3M', '4D', None, None, None, None)
答案 2 :(得分:1)
JavaScript不支持/x
(自由间距或评论模式),因此请在使用前删除此正则表达式中的空格。
/^P(?=.)
(?:\d+Y)?
(?:\d+M)?
(?:\d+D)?
(?:T(?=.)
(?:\d+H)?
(?:\d+M)?
(?:\d+
(?:\.\d{1,2})?
)?
)?$/i
每个(?=.)
前瞻声明在比赛中该点至少有一个角色。这意味着以下组中的至少一个(即,P之后的Y,M,D或T组,以及T之后的H,M或S组)必须匹配,即使它们都是可选的。这满足了更新规范中第二个增加的要求。
答案 3 :(得分:1)
也许它是语义,但SCORM规范的这一部分可以解释为即使没有提供值也允许文字:
字符文字指示符P, 如果,则出现Y,M,D,T,H,M和S. 相应的非零值是 本。
“将出现”意味着如果存在相应的数字,则必须存在文字;如果存在相应的数字,它不会说“仅出现”。
我修改了Alan的正则表达式以处理这种可能性(谢谢,Alan):
^P(?:\d+Y|Y)?(?:\d+M|M)?(?:\d+D|D)?(?:T(?:\d+H|H)?(?:\d+M|M)?(?:\d+(?:\.\d{1,2})?S|S)?)?$
到目前为止,我发现的唯一错误是未能标记未指定数值的字符串,例如'PTS'。根据规范的最小值是“P”,后跟单个值和随附的名称,例如P1Y(= 1年)或PT0S(= 1秒):
至少一个字符文字 应有指示符和价值 除了指示符P
必须有一种方法可以为这个正则表达式添加一个数值检查,但我的正则表达式并不强大。 :)
答案 4 :(得分:1)
对于它的价值,我已经采用了与Cold Fusion一起使用的已接受答案。我以为有些人可能觉得它很有用,所以我想我会发布它。如上所述,CF轰炸了上面的秒实现,所以我修改了它。我不确定这是否意味着它是上述示例中的一般RegEx错误,或者CF和JS是否有不同的RegEx实现。无论如何,这是CF RegEx,附有评论(因为,你知道,否则正则表达式完全是胡言乱语):
<cfset regex = "(?x) ## allow for multi-line expression, including comments (oh, glorious comments)
^ ## ensure that this expression occurs at the start of the string
P ## the first character must be a P
(\d+Y|Y)? ## year (the ? indicates 0 or 1 times)
(\d+M|M)? ## month
(\d+D|D)? ## day
(?:T ## T delineates between day and time information
(\d+H|H)? ## hour
(\d+M|M)? ## minute
(\d+(?:\.\d{1,2})?S|S)? ## seconds and milliseconds. The inner ?: ensure that the sub-sub-expression isn't returned as a separate thing
)? ## closes 'T' subexpression
$ ## ensure that this expression occurs at the end of the string. In conjunction with leading ^, this ensures that the string has no extraenous characters">
之后,你可以像这样对你的字符串运行它:
<cfset result = reFind(regex,mystring,1,true)>
返回一个子表达式数组,您可以迭代它们以获得谨慎的部分:
<cfloop from=1 to=#arrayLen(result.len)# index=i>
<cfif result.len[i] GT 0>
#mid(mystring, result.pos[i], result.len[i])#<br>
</cfif>
</cfloop>
答案 5 :(得分:0)
我们的SCORM Engine实现使用了与上述类似的正则表达式的组合,并且一些基本的JavaScript逻辑确实进行了进一步的验证。
答案 6 :(得分:0)
我正在使用这个表达式:
^P(\d+Y)?(\d+M)?(\d+D)?(T(((\d+H)(\d+M)?(\d+(\.\d{1,2})?S)?)|((\d+M)(\d+(\.\d{1,2})?S)?)|((\d+(\.\d{1,2})?S))))?$
此表达式与“PYMDT0H”之类的值不匹配:指定符号必须与数字匹配。
答案 7 :(得分:0)
基于之前接受的答案,我已经为PCRE制作了这个捕获正则表达式(PHP,ruby,Ecmascript 2018,...):https://regex101.com/r/KfMs1I/6
^P
(?=\w*\d)
(?:(?<years>\d+)Y|Y)?
(?:(?<month>\d+)M|M)?
(?:(?<days>\d+)D|D)?
(?:
T
(?:(?<hours>\d+)H|H)?
(?:(?<minutes>\d+)M|M)?
(?:
(?<seconds>
\d+
(?:
\.
\d{1,2}
)?
)S
|
S
)?
)?$
不幸的是我在当前的JS中找不到如何做同样的事情,因为在没有命名组的情况下无法以可靠的方式访问可选组。