【问题标题】:preg_match to capture string part after a special characterpreg_match 在特殊字符之后捕获字符串部分
【发布时间】:2012-02-09 20:09:41
【问题描述】:

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

字符串是这样的:

Joao.Martins.G2R71.Pedro.Feliz.sno

Being: NAME 1st player (only first or first+surname) G = game (可以是 2 或 02 或其他小于 99 的数字) ; R = 结果(在本例中主队为 7x1)和 NAME 2nd player ... 最后 3 个字符是游戏类型(本例中的斯诺克)

但字符串也可以是:

Joao Martins |2x71| Pedro Feliz.poo

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

我已经有了这个:

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

但这只是给了我|之间的所有东西|部分甚至没有将它们分开并忽略其他所有内容

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

提前致谢!

【问题讨论】:

    标签: php string preg-match


    【解决方案1】:

    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 个部分,你会习惯*? (贪婪的杀手)。

    $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
    }
    

    编辑(超过 2 个名字)

    如果玩家可能有两个以上的名字(如Armin Van Buuren),你应该像这样使用正则表达式:

    ~^([\w.]+)\.G(\d+)R(\d+)\.([\w.]+)\.(\w+)$~

    这将匹配 Albert.EinsteinArmin.Van.Buuren 中的名称(正则表达式依赖于该名称不会包含 \d(十进制数字),因此像 Gerold The 3rd 这样的名称将不匹配)。

    您应该可以只使用:~^([\w\d.]+)\.G(\d+)R(\d+)\.([\w\d.]+)\.(\w+)$~,它也可以匹配 Gerold The 3rd 和任何其他名称(\.G(\d+)R(\d+)\. 非常严格,您必须编造非常疯狂的名称,例如 G3R01(例如“3l1t33孩子 Gerold") 来解析它。

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

    正则表达式解释

    • ~~ - regexp delimiter;开始结束结束正则表达式; ~regexp~,几乎可以是任何东西/regexp/(regexp)
    • ^$ - meta characters;^ 字符串/行的开头,$ 字符串/行的结尾
    • \wescape sequence 对于任何单词字符,与 [a-zA-Z] 相同
    • ([\w.]+) - 至少捕获一次 subpatern/match group 包含 [a-zA-Z.] 的内容。 + 被称为 quantifier
    • +? - ?(在其他量词之后)被称为贪婪杀手,这意味着尽可能少,通常(\w+)a会匹配(在字符串ababa上)abab(\w+?)a 将匹配 ab(\w*?)a 将匹配空字符串:)

    【讨论】:

    • 好的!我现在正在尝试实施您的 preg_match 建议的方式......它对于第二种类型的字符串完美无缺,但对于第一种类型它不起作用......是不是因为玩家有时可能有 2 个姓氏而不仅仅是1?如果中间的东西是|GxRR|无论如何都完美无缺!我希望我能像你们一样写这些正则表达式!
    • @AfonsoGomes 给你,现在好吗?
    • 啊啊!现在完美运行!!!你救了我! :) 现在我真的很想借此机会尝试理解表达式... ~^ 和 $^ 做了什么?他们是开始和结束“操作员”吗? ([\w.]+) 部分到底是什么,表达式的结尾部分有什么不同?无论如何......非常感谢你的时间,已经投票赞成工作的麻烦和最佳答案:)
    • 现在看到另一个问题 :( 如果球员的名字有一个 - (hifen) 就像切尔西的经理名字安德烈·比利亚斯-博阿斯一样呢?似乎不适用于这种情况。
    • @AfonsoGomes 我已经编辑了我的答案(希望他们不会因为它的长度而私刑我):) 这些链接是学习的好地方......如果这是对你问题的回答,请打勾标记并将其标记为问题答案';添加连字符到组 -> [\w.-] (注意在最后添加它,它有特殊含义)
    【解决方案2】:

    我想这会为你做的。

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

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

    【讨论】:

    • 我在regexplanet.com/simple/index.html 测试了这个表达式,但什么也没发生:|表达有问题吗?我的知识还不够,甚至不敢排查问题!
    • @AfonsoGomes 修复了正则表达式在粘贴时不知道发生了什么。此外,该正则表达式测试器不接受模式中的前导和尾随 /,因此请删除它们以使其正常工作。
    【解决方案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 函数。

    【讨论】:

    • @ThinkingMoney:已经投票赞成您的回答,因为您花时间提供帮助。即使在今天我也会对其进行测试,所以看看它是否也对我有用并吸收更多经验,但 Vyktor 已经使用正则表达式为我提供了一个可行的解决方案(我也想尝试和学习)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多