带有乱码文本的递归正则表达式?获取“ArrayArray”

时间:2011-12-30 01:42:44

标签: php regex serialization recursive-regex

我问了一个类似的问题,但由于过于宽泛而被关闭了。基本上,我有很多这样的问题。我希望只是问一个会更容易。我已经尝试了一些不同的方法来解决这个问题,但它们都没有真正起作用。

我有一个包含大量数据的文本文件。我感兴趣的唯一数据落在两个括号之间,“(”“)”。我想知道如何将括号之间的每个信息实例都放到一个数组中。

我正在使用的代码现在返回ArrayArray

function get_between($startString, $endString, $myFile){
  preg_match_all('/\$startString([^$endString]+)\}/', $myFile, $matches);
  return $matches;
}
$myFile = file_get_contents('explode.txt');
$list = get_between("&nbsp(", ")", $myFile);
foreach($list as $list){
  echo $list;
}

2 个答案:

答案 0 :(得分:2)

你的正则表达式完全被误导了。

首先:[^...]是一个补充的字符类。补充的字符类是一个原子,无论...是什么,在这一点上必须的字符集。也就是说,[^ab]将允许除ab之外的所有内容。

第二:你似乎希望能够在parens之间捕获。但是paren(开放或结束)是正则表达式中的特殊角色。因此,在您的示例中,如果$startString&nbsp(,则paren将被解释为正则表达式元字符。

第三:遗憾的是,这不能通过正则表达式解决,但嵌套的$startString$endString无法匹配(好吧,它们可以与perl匹配,但perl是perl)。

最接近你真正想要的是重写你的正则表达式以用于preg_match_all,如下所示:

$start = preg_quote($startString, '/');
$end = preg_quote($endString, '/');
$re = '/\Q' . $start . '\E'       # literal $start
    . '('                         # capture...
    . '(?:(?!\Q' . $end . '\E).)' # any character, as long as $end is not found at this position,
    . '+)'                        # one or more times
    . '\Q' . $end . '\E/';        # literal $end

然后将其用作preg_match_all的第一个参数。

\Q\E正则表达式修饰符告诉第一个和第二个之间的任何内容都应该被视为文字 - 因此&nbsp(中的paren将被字面上对待,而不是小组开幕元字。

答案 1 :(得分:1)

<?php
function get_between($startString, $endString, $myFile){
  //Escape start and end strings.
  $startStringSafe = preg_quote($startString, '/');
  $endStringSafe = preg_quote($endString, '/');
  //non-greedy match any character between start and end strings. 
  //s modifier should make it also match newlines.
  preg_match_all("/$startStringSafe(.*?)$endStringSafe/s", $myFile, $matches);
  return $matches;
}
$myFile = 'fkdhkvdf(mat(((ch1)vdsf b(match2) dhdughfdgs (match3)';
$list = get_between("(", ")", $myFile);
foreach($list[1] as $list){
  echo $list."\n";
}

我这样做了,似乎有效。 (显然,你需要用你的file_get_contents语句替换我的$ myFile赋值行。)一些事情:

答:单引号不会发生变量替换。所以你的preg_replace_all正则表达式不会起作用。因为它实际上将$ startString添加到你的表达式而不是(。(我还在匹配字符串的末尾删除了check}。如果你需要在结束分隔符之前使用\\},请将其添加回来。)

B:$ list将是一个数组数组。我相信默认情况下,索引零将包含所有完整匹配。 index one将包含第一个子模式匹配。

C:只有在您尝试匹配的子模式中找不到$ endString时,这才有效。比方说,如果你期望(matc(fF))给你matc(fF),它就不会。它会给你匹配(fF。如果你想在这种情况下得到前一个结果,你需要一个更强大的解析器。

修改:此处的get_between函数也适用于&nbsp;()},或者您想要的任何其他内容。