3

在尝试 10 次重写这个问题以被接受后,我有一个小文本,括号之间有文本,我想提取该文本,所以我写了这个表达式:

/(\([^\)]+\))/i

但这只会在第一个(和最后一个之间提取文本,而)忽略其余文本,所以有什么方法可以提取全文,例如:

i want(to) extract this text

从 :

this is the text that (i want(to) extract this text) from

可能有不止一个括号括起来的 sub-text 。

谢谢

编辑 发现这个:

preg_match_all("/\((([^()]*|(?R))*)\)/", $rejoin, $matches);

从接受的答案中提供的链接非常有用

4

4 回答 4

6

是的,您可以使用此模式

   v                   v
 (\([^\)\(]*)+([^\)\(]*\))+
 ------------ -------------
      |            |
      |            |->match all (right)brackets to the right..
      |
      |->match all (left)brackets to the left

演示


如果您有这样的递归模式,上述模式将不起作用

(i want(to) (extract and also (this)) this text)
                              ------
            -------------------------

在这种情况下,您可以使用elclanrs 推荐的递归模式


您也可以在(使用正则表达式的情况下通过维护和的数量来做到这一点)

所以,假设noOfLB是 的计数是(noOfRB计数)

  • 继续迭代字符串中的每个字符并保持first的位置 (
  • 如果发现 (
  • 如果你发现增加 noOfRB )
  • if noOfLB==noOfRB,你找到了last的最后位置 )

我不知道php所以我会在c#中实现上面的算法

public static string getFirstRecursivePattern(string input)
{
    int firstB=input.IndexOf("("),noOfLB=0,noOfRB=0;
    for(int i=firstB;i<input.Length && i>=0;i++)
    {
         if(input[i]=='(')noOfLB++;
         if(input[i]==')')noOfRB++;
         if(noOfLB==noOfRB)return input.Substring(firstB,i-firstB+1);
    }
    return "";
}
于 2013-07-03T03:27:16.360 回答
2

您将需要递归子模式来解决这个问题。这是应该为您工作的正则表达式:

$str = 'this is the text that (i want(to) extract this text) from';
if (preg_match('/\s* \( ( (?: [^()]* | (?0) )+ ) \) /x', $str, $arr))
   var_dump($arr);

输出:

string(28) "i want(to) extract this text"
于 2013-07-03T04:53:45.283 回答
0

您还可以使用子字符串:

$yourString = "this is the text that (i want(to) extract this text) from";

$stringAfterFirstParen = substr( strstr( $yourString, "(" ), 1 );

$indexOfLastParen = strrpos( $stringAfterFirstParen, ")" );

$stringBetweenParens = substr( $stringAfterFirstParen, 0, $indexOfLastParen );
于 2013-07-03T03:33:20.713 回答
0

我想我理解这个问题,那就是您想从可能看起来像这样的内容中提取“我想要(要)提取此文本”或类似内容:这是(我想要(要)提取此文本的文本) 从

如果是这样,您可能会通过以下正则表达式找到成功(使用 $text 定义正在检查的变量,并将 $txt 作为在匹配的情况下创建的变量,然后将其存储在数组 $t[] 中):

if (preg_match('/\(\w+.+\)/', $text, $t)) {
$txt = $t[0];
} else {
$txt = "";
}
echo $desired=substr($txt,1,-1);

其根的 RegEx 是: (\w+.+) ,这里是代码的解释:

  1. 匹配字符“(”字面意思是«(»
  2. 匹配作为“单词字符”的单个字符(字母、数字和下划线)«\w+» 在一次和无限次之间,尽可能多次,根据需要返回(贪婪)«+»
  3. 匹配任何不是换行符的单个字符«.+» 一次到无限次,尽可能多次,根据需要返回(贪婪)«+»
  4. 从字面上匹配字符“)”«)»
  5. 将括号内的文本放入新变量 $desired。通过选择在任一端减少一个字符的子字符串来显示 $desired 字符,从而消除边界括号。«echo $desired=substr($txt,1-1)»

使用上面的内容,我可以显示:我想(要)从变量 $text 中提取此文本 = 这是(我想(要)从中提取此文本)的文本。如果希望从 (to) 中提取“to”,我建议您通过正则表达式循环运行变量,直到在表达式中找不到更多 (),它返回一个空值并将返回的值连接到形成感兴趣的变量。

祝你好运,史蒂夫

于 2013-07-03T05:17:36.517 回答