2015-04-12 41 views
0

我真的不知道我需要什麼來解決這個問題,但我試圖從以下瀏覽器中提取操作系統,操作系統版本和iPhone,Macintosh等品牌:正則表達式和/或/包含在PHP中

Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.34 (KHTML, like Gecko) Dooble/1.40 Safari/534.34 
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A 
Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419. 
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1 
Mozilla/5.0 (Windows; U; Windows NT 6.1; tr-TR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27 
Mozilla/5.0 (Linux; U; Android 2.2.1; zh-tw; HTC_Sensation_S710e Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 
Mozilla/5.0 (Windows; U; Windows NT 6.0; nl) AppleWebKit/522.13.1 (KHTML, like Gecko) Version/3.0.2 Safari/522.13.1 
Mozilla/5.0 (BlackBerry; U; BlackBerry 9700; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.380 Mobile Safari/534.8+ 

我不知道我是否需要match_all,match,replace,split。 字符串不都是一樣的,而且我想下面的正則表達式:

preg_match_all('/\((.*?);|\((.*?)\) AppleWebKit/im', $user_agent, $brandmatch, PREG_PATTERN_ORDER); 

其中有這樣的結果,這是很好的:

Macintosh 
iPhone 
Macintosh 
Windows 
Linux 
Windows 
BlackBerry 
Windows NT 5.1 

preg_match_all('/\(.*?; (.*?)\)/im', $user_agent, $brandmatch, PREG_PATTERN_ORDER); 

其中有這樣的結果:(我想1 - 6是象0)

0 => Intel Mac OS X 10_9_3 
1 => U; CPU like Mac OS X 
2 => U; Intel Mac OS X 10_6_8; de-at 
3 => U; Windows NT 6.1; tr-TR 
4 => U; Android 2.2.1; zh-tw; HTC_Sensation_S710e Build/FRG83D 
5 => U; Windows NT 6.0; nl 
6 => U; BlackBerry 9700; en-US 

所以,我試圖執行以下操作:

preg_match_all('/U; (.*?);/im', $user_agent, $brandmatch, PREG_PATTERN_ORDER); 

其中有這樣的結果:(它比上面少2,這是壞的)

0 => Intel Mac OS X 10_6_8 
1 => Windows NT 6.1 
2 => Android 2.2.1 
3 => Windows NT 6.0 
4 => BlackBerry 9700 

所以我試圖做的是:我想要的OS + OS版本。我也試過:

\(.*?; (.*?)\)|U; (.*?); 

其中有這樣的結果:

0 => Intel Mac OS X 10_9_3 
1 => U; CPU like Mac OS X 
2 => U; Intel Mac OS X 10_6_8; de-at 
3 => U; Windows NT 6.1; tr-TR 
4 => U; Android 2.2.1; zh-tw; HTC_Sensation_S710e Build/FRG83D 
5 => U; Windows NT 6.0; nl 
6 => U; BlackBerry 9700; en-US 

所以我需要的結果是:

0 => Intel Mac OS X 10_9_3 
1 => CPU like Mac OS X 
2 => Intel Mac OS X 10_6_8 
3 => Windows NT 6.1 
4 => Android 2.2.1 
5 => Windows NT 6.0 
6 => BlackBerry 9700 
+0

使用另一個正則表達式刪除在第一個「;」之前的所有內容以及在此之前的第一個「之後」。在最後一次出現';'後刪除所有內容。不幸的是我不知道php正則表達式,但是在sed中它看起來像這樣:'^ \(。* \)[^] *; \([^;] \);。* $ *'捕獲第一和第二組(之間的'\(\)'。 – ShellFish

回答

2

分支復位功能,您可能會感興趣,因爲它允許多種替代方案,但每個替代方案與其他方案共享相同的捕獲組。

分支復位是這樣的:

(?|alternat(ive1)|alternati(ve2)|alternat(ive3)|e(tc.)) 

你可以看到四個捕獲組,但在這種結構中,捕獲組是相同的(所以只有一個捕獲組定義及其含量取決於成功的分支)。

對於你的問題,你可以嘗試寫這樣的事:

~^[^(]*\((?|[^);]*;(?: U;)? ([^;)]+)|([^)]+))~m 

demo

所有你以後需要的是提取捕獲組1


的其他方式:使用\K功能

Th e \K從匹配結果中刪除以前匹配的所有內容。因此,沒有必要定義捕獲組,整場比賽可結果:

~^[^(]*\((?:[^);]*;(?: U;)? \K[^;)]+|\K[^)]+)~m 

demo


但有一個更輕的方法:使第一交替可選的開頭,並刪除第二:

^[^(]*\((?:[^);]*;(?: U;)?)?\K[^;)]+~m 

demo

2

你可以使用這個表達式:

/^\S+ +\((?:[^;\n]*;)?(?: U;)?([^;)]+)/m 

RegEx Demo

  • 首先它匹配高達第一空間
  • 然後它(然後0個或多個字符,直到匹配後跟一個;換行符或;一切。
  • 然後將其可選的比賽U;
  • 它抓住一切直到);在匹配組#發現1
  • 更多詳情請看演示
+1

解釋還清:) – Rizier123

+0

謝謝,但這不承認Windows NT 5.1。 – MOTIVECODEX

+0

這是根據您的**預期結果**作爲第一個結果,您已將英特爾®Mac OS X 10_9_3作爲其中的一員。你期望'Windows NT 5.1'也可以匹配嗎? – anubhava