识别结构化文本字符串中的随机重复模式

时间:2011-03-25 00:32:02

标签: php

我有一个具有以下结构的字符串:

ABC_ABC_PQR_XYZ

PQR具有以下结构:

ABC+JKL

ABC本身是一个字符串,可以包含字母数字字符和一些其他字符,如“_”,“ - ”,“+”,“。”并且没有设置结构:

例如。qWe_rtY-asdfpkl123

所以,实际上,字符串可能如下所示:

qWe_rtY-asdf_qWe_rtY-asdf_qWe_rtY-asdf+JKL_XYZ

我的目标是找出构成ABC的字符串。

我最初刚刚使用

$arrString = explode("_",$string);

在我意识到$arrString[0]ABC)本身可以包含下划线之前返回$arrString[0],从而使其不正确。

我的下一次尝试无论如何都要在“_”上进行扩展,然后将每个爆炸的字符串部分与第一个字符串部分进行比较,直到我得到一个模式的外观:

function getPatternABC($string)
{
 $count  = 0;
 $pattern ="";

 $arrString = explode("_", $string);

 foreach($arrString as $expString)
 {
    if(strcmp($expString,$arrString[0])!==0 || $count==0)
{
   $pattern = $pattern ."_". $arrString[$count];
   $count++;
    }
    else break;
 }

 return substr($pattern,1);
}

这很有效 - 但我想知道使用正则表达式是否有更优雅的方法吗?

3 个答案:

答案 0 :(得分:1)

这是正则表达式解决方案:

'^([a-zA-Z0-9_+-]+)_\1_\1\+'

这样做是匹配(从字符串的开头开始)最长的序列,由方括号内的字符组成(根据您的规范编辑)。序列必须恰好出现两次,每次后跟一个下划线,然后必须再出现一个加号(这实际上是PQR的前半部分,而JKL之前的分隔符)。输入的其余部分将被忽略。

您会发现ABC被捕获为捕获组1。

所以:

$input = 'qWe_rtY-asdf_qWe_rtY-asdf_qWe_rtY-asdf+JKL_XYZ';
$result = preg_match('/^([a-zA-Z0-9_+-]+)_\1_\1\+/', $input, $matches);
if ($result) {
    echo $matches[2];
}

See it in action

答案 1 :(得分:1)

当然,只需创建一个与您的模式匹配的正则表达式。在这种情况下,像这样:

preg_match('/^([a-zA-Z0-9_+.-]+)_\1_\1\+JKL_XYZ$/', $string, $match);

你的ABC在$ match [1]。

答案 2 :(得分:0)

如果这些字符串中的下划线存在频率较低,则可能需要检查一下简单的explode()是否会在使用正则表达式之前执行此操作。

<?php
$str = 'ABC_ABC_PQR_XYZ';
if(substr_count($str, '_') == 3)
   $abc = reset(explode('_', $str));
else
   $abc = regexy_function($str);
?>