2015-04-12 89 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