我有以下价值:
start=2011-03-10T13:00:00Z;end=2011-03-30T13:00:00Z;scheme=W3C-DTF
我使用以下正则表达式去除'开始'和'结束'日期并将它们分配给它们自己的命名捕获对:
#^start=(?P<publishDate>.+);end=(?P<expirationDate>.+);#ix'
可能不是绝对最好的REGEX,但如果“开始”和“结束”值都存在,它就足够好了。
现在,如果“expirationDate”丢失,我需要做的仍然是匹配'publishDate',反之亦然。
如何使用单个表达式执行此操作?我不是正则表达式中最伟大的,我开始徘徊于更高级的东西,所以对此的任何帮助都将非常感激。
谢谢!
更新
感谢钟先生,我已用以下表达式解决了这个问题:
#^(start=(?P<publishDate>.*?);)?(end=(?P<expirationDate>.*?);)?#xi
一如既往,非常感谢大家的帮助。 :)
答案 0 :(得分:4)
使用(...)?对于可选部分
^(start=(?P<publishDate>.+);)?(end=(?P<expirationDate>.+));)?
答案 1 :(得分:2)
这两个都将命名缓冲区设置为一个值(而不是null或undefined) 我推荐第一个。
1。以任意顺序查找/两者:
/^(?=.*\bstart=(?P<publishDate>.*?);|(?P<publishDate>))(?=.*\bend=(?P<expirationDate>.*?);|(?P<expirationDate>))/ix
/^(?= # from beginning, look ahead for start
.*\b # any character 0 or more times (backtrack to match 'start')
start=(?P<publishDate>.*?); # put start date in publish
| (?P<publishDate>) # OR, put empty string publish
)
(?= # from beginning, look ahead for end
.*\b # same criteria as above ...
end=(?P<expirationDate>.*?);
| (?P<expirationDate>)
)
/ix
2. 要按开始/结束顺序查找/两者:
/^(?:.*\bstart=(?P<publishDate>.*?);|(?P<publishDate>))(?:.*\bend=(?P<expirationDate>.*?);|(?P<expirationDate>))/ix
修改
@Josh Davis - 我不得不去寻找PCRE.org,那里有一些很棒的东西。使用Perl,重复名称没有问题 文档:“如果多个组具有相同的名称,则它指的是当前匹配中最左侧定义的组。” 在交替使用时,这绝不是问题。
使用PCRE ..
如果重复的名称与分支重置一起使用,则它将与PHP一起正常工作
分支重置可确保重复的名称将占用相同的捕获组
之后,使用dup名称常量,$ match ['name']将包含值
或空字符串,但它会存在。
即:
(?J)= PCRE_DUPNAMES
(?| ... | ...)=分支重置
这有效:
/(?Ji)^
(?= (?| .* end = (?P<expirationDate> .*? ); | (?P<expirationDate>)) )
(?= (?| .* start = (?P<publishDate> .*? ); | (?P<publishDate>)) )
/x
在此处试试:http://www.ideone.com/zYd24
<?php
$string = "start=2011-03-(start)10T13:00:00Z;end=2011-03-(end)30T13:00:00Z;scheme=W3C-DTF";
preg_match('/(?Ji)^
(?= (?| .* end = (?P<expirationDate> .*? ); | (?P<expirationDate>)) )
(?= (?| .* start = (?P<publishDate> .*? ); | (?P<publishDate>)) )
/x', $string, $matches);
echo "Published = ",$matches['publishDate'],"\n";
echo "Expires = ",$matches['expirationDate'],"\n";
print_r($matches);
?>
输出
Published = 2011-03-(start)10T13:00:00Z
Expires = 2011-03-(end)30T13:00:00Z
Array
(
[0] =>
[expirationDate] => 2011-03-(end)30T13:00:00Z
[1] => 2011-03-(end)30T13:00:00Z
[publishDate] => 2011-03-(start)10T13:00:00Z
[2] => 2011-03-(start)10T13:00:00Z
)
答案 2 :(得分:0)
如果'start =;'在没有相应日期时不存在,那么Stephen Chung的代码就可以了
否则我认为用'*'代替'+'就足够了:
#^start=(?P<publishDate>.*?);end=(?P<expirationDate>.*?);#ix'
顺便说一句,'?'是必要的,以便在每个代码中都不明白