preg_match在特殊字符后捕获字符串部分

时间:2012-02-09 20:09:41

标签: php string preg-match

我有一个包含字符串的文本文件,对于每个字符串,我需要划分并捕获它的每个部分。

字符串就像:

Joao.Martins.G2R71.Pedro.Feliz.sno

存在:NAME第一个玩家(只有第一个或第一个+姓氏)G =游戏(可以是2或02或其他小于99的数字); R =结果(在这个例子中主队7x1)和NAME第2名球员......最后3个比赛是比赛类型(这个例子斯诺克)

但字符串也可以是:

Joao Martins |2x71| Pedro Feliz.poo

我不是正则表达专家(遗憾地)并且已经在这里搜索了很多问题而没有找到解决方案,或者只是通过阅读其他问题的答案获得帮助(主要是因为我似乎从未理解这一点)

我已经有了这个:

preg_match("/\[(|^|]+)\]/",$string,$result);
echo $result[1] . "<br />";

但这只能给我一切之间的所有东西|部分甚至没有分开它们而忽略了其他一切

你们可以帮我解决这两种情况吗?我像往常一样完全迷失在这里!

提前致谢!

3 个答案:

答案 0 :(得分:4)

explode方式:

您不必使用复杂的正则表达式,您可以使用简单的explode

$parts = explode( '.', $string);

零件现在如何2件或6件,所以你可以这样做:

if( count( $parts) == 6)){
   list( $fistName1, $surName1, $string, $fistName2, $surName2, $gameType) = $parts;
} elseif( count( $parts) == 2) {
   $gameType = $parts[1];
   list( $fistName1, $surName1, $string, $fistName2, $surName2) = explode( $parts[0]);
} else {
   echo "Cannot parse";
}

现在解析$gameType:)

if( preg_match( '~^\|(\d+)x(\d+)\|$~', $gameType, $parts)){
   $first = $parts[1];
   $second = $parts[2];
} elseif( preg_match( '~^G(\d+)R(\d+)$~', $gameType, $parts)){
   $first = $parts[1];
   $second = $parts[2];
} else {
   echo "Cannot parse!";
}

preg_match方式:

第二个正则表达式是故意不同的,所以你可以看到如何编写将“吃掉”全名的正则表达无论是否有2,3或5个部分你都会习惯{{1 (贪婪的杀手)。

*?

编辑(超过2个名字)

如果玩家可能拥有超过2个名字(如$match = array(); if( preg_match( '~^(\w+)\.(\w+)\.G(\d+)R(\d+)\.(\w+)\.(\w+)\.(\w+)$~', $text, $match)){ // First way } elseif (preg_match( '~^([^\|]+)\|(\d+)x(\d+)\|(.*?)\.(\w+)$~', $text, $match)){ // Second way } else { // Failed to parse } ),你应该使用这样的正则表达式:

Armin Van Buuren

这将匹配~^([\w.]+)\.G(\d+)R(\d+)\.([\w.]+)\.(\w+)$~Albert.Einstein中的名称(regexp依赖于该名称将不包含Armin.Van.Buuren(十进制数字),因此\d之类的名称将不匹配)。

你应该没问题:Gerold The 3rd也会匹配~^([\w\d.]+)\.G(\d+)R(\d+)\.([\w\d.]+)\.(\w+)$~而任何其他名称(Gerold The 3rd都非常严格,你必须像{一样真正疯狂的名字{1}}(如“3l1t33 kid Gerold”)解析错误。

哦,还有一件事,别忘了$name = strtr( $name, '.', ' '):)

RegExp解释

  • \.G(\d+)R(\d+)\. - regexp delimiter;开始结束regexp; G3R01,它实际上可以是~~~regexp~
  • /regexp/(regexp) - meta characters; ^字符串/行的开头,$字符串/行的结尾
  • 对于任何单词字符,
  • ^escape sequence,与$相同
  • \w - 至少抓取subpatern/match group包含[a-zA-Z]的内容。 ([\w.]+)被称为quantifier
  • [a-zA-Z.] - +(在其他量词之后)被称为贪婪杀手,它意味着尽可能少地,通常会+?匹配(在字符串?(\w+)aababa匹配abab(\w+?)a匹配空字符串:)

答案 1 :(得分:4)

我认为这会为你做到。

    /^(\w+)(?:\.| )(\w+)(?:\.| \|)G?(\d+)[x|R](\d+)(?:\.|\| )(\w+)(?:\.| )(\w+)(?:\.| )(\w+)$/
  • $ 1将是p1名字
  • $ 2将是p1姓氏
  • $ 3将是游戏编号
  • $ 4将成为结果
  • $ 5将是p2名字
  • $ 6将是p2姓氏
  • $ 7将是游戏类型

如果$ n的东西没有意义,那么只需将它们视为$ results数组的元素。模式可能会简化一些,但我没有足够的时间来弄明白。

答案 2 :(得分:3)

你可以这样做:

//to get the string without the game type
$yourstring = substr($yourstring ,0 ,strlen($yourstring)-4);

//separating strings with "." as delimiter
$results = explode(".",$yourstring);

//checking whether "." was the delimiter 
if(!strcmp($results[0],$yourstring)) {
  //if "." was not the delimiter, then split the string with " " 
  //as the delimiter.
  $results = explode(" ",$yourstring);
  }

//storing them in separate variables. and removing "|" if exists.
if( count( $results) == 5){
  $results[2] = trim($results[2],"|");
  list( $var1, $var2, $var3, $var4, $var5) = $results;
  }
elseif( count( $results) == 4){
  $results[1] = trim($results[1],"|");  
  $results[2] = trim($results[2],"|");  
  list( $var1, $var2, $var3, $var4) = $results;
  }
else {
  $results[1] = trim($results[1],"|");  
  list( $var1, $var2, $var3) = $results;
  }

所有字符串部分将被分隔并存储在$results中。 要使它们分离变量,您可以使用list函数。