我有一个rule
字段的数组,其字符串如下:
FREQ=MONTHLY;BYDAY=3FR
FREQ=MONTHLY;BYDAY=3SA
FREQ=WEEKLY;UNTIL=20170728T080000Z;BYDAY=MO,TU,WE,TH,FR
FREQ=MONTHLY;UNTIL=20170527T100000Z;BYDAY=4SA
FREQ=WEEKLY;BYDAY=SA
FREQ=WEEKLY;INTERVAL=2;BYDAY=TH
FREQ=WEEKLY;BYDAY=TH
FREQ=WEEKLY;UNTIL=20170610T085959Z;BYDAY=SA
FREQ=MONTHLY;BYDAY=2TH
每一行都是一个不同的数组,我提供了一些线索来了解我的需求。
我需要的是编写一个可以取消所有不必要值的正则表达式。
所以,我不需要FREQ =; BYDAY =等我基本上需要在=之后的值,但每个我想存储在一个不同的变量中。
以第三个为例,它将是:
$frequency = WEEKLY
$until = 20170728T080000Z
$day = MO, TU, WE, TH, FR
它不一定是一个正则表达式,每个值可以有一个正则表达式。所以我有一个FREQ:
preg_match("/[^FREQ=][A-Z]+/", $input_line, $output_array);
但不幸的是,我不能为其他人做这件事,我怎么能解决这个问题?
答案 0 :(得分:2)
唯一的方法是PHP数组解构:
$str = "FREQ=WEEKLY;UNTIL=20170728T080000Z;BYDAY=MO,TU,WE,TH,FR";
preg_match_all('~(\w+)=([^;]+)~', $str, $matches);
[$freq, $until, $byday] = $matches[2]; // As of PHP 7.1 (otherwise use list() function)
echo $freq, " ", $until, " ", $byday;
// WEEKLY 20170728T080000Z MO,TU,WE,TH,FR
使用extract
功能:
preg_match_all('~(\w+)=([^;]+)~', $str, $m);
$m[1] = array_map('strtolower', $m[1]);
$vars = array_combine($m[1], $m[2]);
extract($vars);
echo $freq, " ", $until, " ", $byday;
答案 1 :(得分:1)
注意:对于这个问题,我建议使用@revo发布的generell方法,它简洁,安全且容易上手 - 但请记住,与固定字符串函数相比,正则表达式会带来性能损失,所以如果你可以使用strpos / substr / explode / ...,尝试使用它们,不要“膝盖反射”到基于preg_的解决方案。
由于分隔符是固定的,并且似乎没有出现在您感兴趣的值中,并且您还依赖于键的知识(FREQ:等),因此您不需要使用正则表达式(尽可能多我喜欢在任何地方使用它们,你可以在这里使用它们;为什么不简单地在这种情况下爆炸和分裂?
$lines = explode("\n", $text);
foreach($lines as $line) {
$parts = explode(';', $line);
$frequency = $until = $day = $interval = null;
foreach($parts as $part) {
list($key, $value) = explode('=', $part);
switch($key) {
case 'FREQ':
$frequency = $value;
break;
case 'INTERVAL':
$interval = $value;
break;
// and so on
}
}
doSomethingWithTheValues();
}
如果您的用例非常简单,那么这可能更具可读性和效率。
答案 2 :(得分:0)
您需要使用模式
;?[A-Z]+=
与preg_split();
一起使用preg_split('/;?[A-Z]+=/', $str);
解释
; match Semikolon
? no or one of the last Character
[A-Z]+ match one or more uppercase Letters
= match one =
如果你想让每一行成为一个单独的数组,你应该这样做:
# split each Line into an Array-Element
$lines = preg_split('/[\n\r]+/', $str);
# initiate Array for Results
$results = array();
# start Looping trough Lines
foreach($lines as $line){
# split each Line by the Regex mentioned above and
# put the resulting Array into the Results-Array
$results[] = preg_split('/;?[A-Z]+=/', $line);
}