2017-07-02 126 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但它的影響是有限的,因爲它適用於一個原子團體。