2017-07-02 129 views
1

我strugling识别正则表达式如下:PHP的正则表达式识别多个模式

文本:

VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020= 

我想这个词TEMPO后,所有的信息,但它得到下一TEMPO即具有所有实例的阵列

例如在这个例子中

1: TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 
2: TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 
3: TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 
4: TEMPO 0303/0306 3500 SHRA FEW015CB SCT020= 

我试图"/TEMPO (.*?) TEMPO/""/TEMPO (.*)\Z/"等等等等,但就是无法破解它。

+0

我可以建议你看看http://www.alexander-ott.com/phpmyeasyweather/它不是100%兼容新版本的PHP,但它很容易修复。它将处理大部分的METAR和TAFs – Andreas

+0

TAF是由它构成还是真实的?在相同的TAF中,能见度10公里 - > 2500米。不要以为我在 – Andreas

+0

之前就已经看到这个答案了吗? – Andreas

回答

1

你可以试试:

TEMPO\s*\K.*?(?=(?:TEMPO|\s*$)) 

Demo

示例代码:(Run here

<?php 
$re = '/TEMPO\s*\K.*?(?=(?:TEMPO|\s*$))/'; 
$str = 'VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020='; 
$result=[]; 
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0); 
foreach ($matches as $mg) 
    array_push($result,$mg[0]); 

print_r($result); 

?> 
-1

即使问题是功能标签的正则表达式,我没有发现beeing的这是最好的解决方案。

我相信一个简单的爆炸会做得很好。

https://3v4l.org/kBsT8

$TAF = "VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020="; 

$Tempo = explode(" TEMPO ", $TAF); 
array_shift($Tempo); //removes the main TAF and leaves the TEMPO 
var_dump($Tempo); 
+0

下载者请解释一下吗?如果你认为我错过了字符串中的'TEMPO',那么我可以说这不是必需的。 OP正在尝试构建METAR/TAF解码器。那是机场天气。我有一个网页,做了完全相同的事情,我知道如果你知道它在那里,TEMPO这个词可以被忽略。是的,我的答案不是正则表达式,但总是提问者选择方法是正确的吗?我不这么认为。当Y好得多的时候,很多时候有人向X求助。请再解释一下为什么downvote。 – Andreas

+0

作为一个例子。如果一个问题是关于解析HTML的正则表达式,你会用正则表达式来解析HTML,还是建议DOM或其​​他东西? – Andreas

+0

谢谢大家的各种代码。解决方案$ TAF =“VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020 PROB40 0211/0212 SHRA BKN025CB BECMG 0212/0214 25015G27KT TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 FM1430 25015G27KT OVC020 SHRA =“; $ delims = ['TEMPO','BECMG','PROB','FM']; ('/(?='。implode('|',$ delims)。')/',$ TAF),1)); var_export(array_slice(preg_split是最好的。 – Trevor

0

而只是因为我可以,我将添加另一个答案,将解决下一个问题OP都会有。

“如何为TEMPO,BECMG,PROBxx和FM处理正则表达式?”

再次...正则表达式不是工具。
这里是一个例子,如何将TAF分成它的“部分”。根据机场和国家,有些可能会被使用,有些可能不会被使用。

我创建了一个“假”TAF只是为了证明我的观点。

$delimiters = array("TEMPO","BECMG", "PROB", "FM"); 
$TAF = "VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020 PROB40 0211/0212 SHRA BKN025CB BECMG 0212/0214 25015G27KT TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 FM1430 25015G27KT OVC020 SHRA="; 


foreach($delimiters as $item){ 
    $TAF = str_replace($item, " " . $item, $TAF); 
} 

$TAFparts = explode(" ", $TAF); 
var_dump($TAFparts); 

输出:

array(9) { 
    [0]=> 
    string(82) "VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z" 
    [1]=> 
    string(47) "TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015" 
    [2]=> 
    string(41) "TEMPO 0215/0221 3500 SHRA FEW015CB SCT020" 
    [3]=> 
    string(47) "TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015" 
    [4]=> 
    string(41) "TEMPO 0303/0306 3500 SHRA FEW015CB SCT020" 
    [5]=> 
    string(30) "PROB40 0211/0212 SHRA BKN025CB" 
    [6]=> 
    string(26) "BECMG 0212/0214 25015G27KT" 
    [7]=> 
    string(47) "TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015" 
    [8]=> 
    string(30) "FM1430 25015G27KT OVC020 SHRA=" 
} 

https://3v4l.org/26nTv

它通过TAF消息的每个新的 “组” 之前加入的空间。
因此,而不是blabla TEMPO我做它blabla TEMPO(双倍空间)。
然后,我可以轻松爆炸双空间。

0

我同意安德烈亚斯的观点 - 通常问题出现在要求基于正则表达式的解决方案上,而不考虑或知道使用非正则表达式方法的可能性。我会敦促你考虑使用非正则表达式的解决方案,只要它不是无理地复杂化就可以这么做。 “

此外,我还看到要求 preg_match_all()”拆分字符串“的问题 - 大多数情况下,这不是基于正则表达式拆分的最佳功能。使用正则表达式分割字符串的php函数是preg_split()

因为你的分隔符是静态的(TEMPO),这个问题可以按理说应该使用非正则表达式的功能来解决。然而,正则表达式解决方案可能是您个人偏好的一个未指定的原因(方便,代码简洁,未来修改等)。

这些都是一些preg_split()方法:

$in='VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020='; 
var_export(array_slice(preg_split('/ TEMPO /',$in),1)); 

输出:

array (
    0 => '0202/0209 2500 -TSRA SHRA FEW010CB SCT015', 
    1 => '0215/0221 3500 SHRA FEW015CB SCT020', 
    2 => '0221/0303 2500 -TSRA SHRA FEW010CB SCT015', 
    3 => '0303/0306 3500 SHRA FEW015CB SCT020=', 
) 

我的方法将运行约10倍比RIZWAN的preg_match_all()方法快。


Andreas的样本......

$TAF = "VHHH 020218Z 0202/0306 20010KT 9999 FEW015 SCT025 TX32/0206Z TX32/0306Z TN27/0222Z TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0215/0221 3500 SHRA FEW015CB SCT020 TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015 TEMPO 0303/0306 3500 SHRA FEW015CB SCT020 PROB40 0211/0212 SHRA BKN025CB BECMG 0212/0214 25015G27KT TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015 FM1430 25015G27KT OVC020 SHRA="; 
$delims=['TEMPO','BECMG','PROB','FM']; 
var_export(array_slice(preg_split('/ (?='.implode('|',$delims).')/',$TAF),1)); 

输出:

array (
    0 => 'TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015', 
    1 => 'TEMPO 0215/0221 3500 SHRA FEW015CB SCT020', 
    2 => 'TEMPO 0221/0303 2500 -TSRA SHRA FEW010CB SCT015', 
    3 => 'TEMPO 0303/0306 3500 SHRA FEW015CB SCT020', 
    4 => 'PROB40 0211/0212 SHRA BKN025CB', 
    5 => 'BECMG 0212/0214 25015G27KT', 
    6 => 'TEMPO 0202/0209 2500 -TSRA SHRA FEW010CB SCT015', 
    7 => 'FM1430 25015G27KT OVC020 SHRA=', 
) 

附:我没有处理机场天气状况的网页。

0

与使preg_split一种方法:

$result = preg_split('~(?:\A.*?\b)?(?=TEMPO\b)\b~', $str, -1, PREG_SPLIT_NO_EMPTY); 

分隔符是字符串,直到第一TEMPO或下一个“TEMPO”的位置的开始。这样你就不必移动结果数组的第一项。

模式的细节:

~ 
(?: # optional non-capturing group (useful for the first match) 
    \A  # start of the string anchor 
    .*? \b # characters until a word boundary 
)? 
(?=TEMPO\b) # lookahead: followed by TEMPO 
\b   # a word-boundary 
~ 

与preg_match_all其他方式:

preg_match_all('~\bTEMPO\b[^T]*(?:\BT[^T]*|T(?!EMPO\b)[^T]*)*~', $str, $matches); 

$result = $matches[0]; 

这样搜索摘自 “TEMPO” 直接个子串,直到下一个,直到字符串的结尾。为了描述内容,直到下一个TEMPO,它使用的展开图案是有效的:

[^T]*     # all that isn't a T 
(?: 
    \BT [^T]*   # a T at a non-word boundary position 
    |     # OR 
    T(?!EMPO\b) [^T]* # a T not followed by EMPO and a word boundary 
)* 

这设计比.*?\b(?=TEMPO\b|$)(惰性限定符需要更多的测试)(?:[^T]|\BT|T(?!EMPO\b))*(交替进行测试更有效率很多次)

你也可以写这样的模式:

~\bTEMPO\b\w*(?>\w+\w*)*?(?=TEMPO\b|$)~ 

它采用了懒惰q但它的影响是有限的,因为它适用于一个原子团体。