正则表达式和/或/ exclude /包含PHP

时间:2015-04-12 13:01:23

标签: php regex

我真的不知道我需要修复这个问题,但是我试图从以下浏览器用户中提取操作系统,操作系统版本以及iPhone,Macintosh等品牌:

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

2 个答案:

答案 0 :(得分:2)

您可以使用此正则表达式:

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

RegEx Demo

  • 首先它匹配第一个空间的所有内容
  • 然后匹配(,然后匹配0个或多个字符,直到换行符或;后跟;
  • 然后它可选匹配U;
  • 它会捕获所有内容,直到在匹配的组#1中找到);
  • 有关详细信息,请参阅演示

答案 1 :(得分:2)

分支重置功能可能会让您感兴趣,因为它允许多个备选方案,但每个备选方案与其他方案共享相同的捕获组。

分支重置是这样的:

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

您可以看到四个捕获组,但在此构造中,捕获组是相同的(因此只定义了一个捕获组,其内容取决于成功的分支)。

对于你的问题,你可以尝试写这样的东西:

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

demo

您需要的只是提取捕获组1


另一种方式:使用\K功能

\K从匹配结果中删除之前匹配的所有内容。因此无需定义捕获组,整个匹配可以是结果:

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

demo


但是有一个更轻松的方法:让第一个轮换的开始可选并删除第二个:

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

demo