如何从字符串中替换{} []()括号之间的所有内容?

时间:2013-11-13 08:17:11

标签: php regex string replace preg-replace

我想删除大括号内的所有内容。例如,如果string是:

[hi] helloz [hello] (hi) {jhihi}

然后,我希望输出只有helloz

我使用以下代码,但在我看来应该有更好的方法,是吗?

$name = "[hi] helloz [hello] (hi) {jhihi}";
$new  =  preg_replace("/\([^)]+\)/","",$name); 
$new = preg_replace('/\[.*\]/', '', $new);  
$new = preg_replace('/\{.*\}/', '', $new);  
echo $new;

3 个答案:

答案 0 :(得分:16)

这应该有效:

$name = "[hi] helloz [hello] (hi) {jhihi}";
echo preg_replace('/[\[{\(].*[\]}\)]/U' , '', $name);

将其粘贴到:http://writecodeonline.com/php/以查看是否有效。

答案 1 :(得分:3)

[旧答案]

如果需要,可以处理嵌套括号和方括号或大括号的模式:

$pattern = '~(?:(\()|(\[)|(\{))(?(1)(?>[^()]++|(?R))*\))(?(2)(?>[^][]++|(?R))*\])(?(3)(?>[^{}]++|(?R))*\})~';

$result = preg_replace($pattern, '', $str);

[编辑]

一种模式,只删除均衡的部分,并考虑到三种括号:

$pattern = '~
    \[ [^][}{)(]*+ (?: (?R) [^][}{)(]* )*+  ]
  |
    \( [^][}{)(]*+ (?: (?R) [^][}{)(]* )*+ \)
  |
    {  [^][}{)(]*+ (?: (?R) [^][}{)(]* )*+  }
~xS';

这种模式效果很好但是当目标只是删除字符串中的括号部分时,额外的类型检查有点过分。但是,它可以用作子模式来检查所有类型的括号是否在字符串中平衡。


只删除平衡良好的部分的模式,但这次只考虑最外面的括号类型,忽略其他类型的括号(与旧答案相同但效率更高且没有无用的条件测试)

$pattern = '~
    \[ ( [^][]*+ (?: \[ (?1) ] [^][]* )*+ )  ]
  |
    \( ( [^)(]*+ (?: \( (?2) ] [^)(]* )*+ ) \)
  |
     { ( [^}{]*+ (?:  { (?3) } [^}{]* )*+ )  }
~xS';

答案 2 :(得分:1)

我为此做了一个功能。它用您想要的文本替换大括号(包括它们)中的文本。它也适用于嵌套大括号。将foo(foo(foo))作为替换的bar将返回foobar。它还允许使用您自己的密钥收集var中的替换文本(在这种情况下,前面的示例将显示foo(foo)作为替换文本)。它不使用正则表达式,不仅允许使用大括号,还允许其他所有内容(但仅限于其单个字符...抱歉)。

function advanced_replace($searchStart, $searchEnd, $replace, $subject, &$assignValue = array(), $addValue = false, $inReplace = false, $valueKey = "") {
    $strlen = strlen( $subject );
    $open = 0;
    $ob = false;
    $ob_message = "";
    $message = "";
    for( $i = 0; $i <= $strlen; $i++ ) {
        $char = substr( $subject, $i, 1 );

        if ($char == $searchStart) {
            $open++;
            $ob = true;
        }
        if ($ob) {
            $ob_message .= $char;
        } else {
            $message .= $char;
        }
        if ($char == $searchEnd) {
            $open--;
            if ($open == 0) {
                $ob = false;
                $message .= ($replace.($addValue!== false && $inReplace?$addValue:""));
                $assignValue[$valueKey.($addValue!== false?$addValue:"")] = $ob_message;
                $ob_message = "";
                if ($addValue !== false) $addValue++;
            }
        }
    }
    return $message; 
}

参数:

  • $searchStart是搜索的起始字符。
  • $searchEnd是搜索的结束字符
  • $replace是替换文字。
  • $subject是所有替换发生的文本

可选元素:

  • &$assignValue是对要存储替换文本的数组变量的引用。可选的
  • $addValue是计算替换时的起始编号。它不是引用,但如果不等于false(0仍然可以),它将被放在$assignValue中的键之后。它在$valueKey之前,因为当$valueKey为空时,它将像普通数组一样计数(如果它不是假的,当然 - 例如 - 0),如array(0 => "foo", 1 => "bar")。每次更换增加1。
  • $inReplace(如果为true)也会在替换后放置$addValue,每次操作都会增加1。
  • $valueKey是用于替换文本数组中所有项目的键。强烈建议在使用时将$addValue设置为非假 - 它将仅返回最后一个项目!

返回值:

它不会更改任何参数,而是$assignValue。它返回修改后的$subject并将$assignValue设置为已替换文本的数组。

实施例

$script = "test: (2+2), test: (3*(1+2))";
$script = advanced_replace("(",")", '?_MATH', $script, $vars, 0, true, '_MATH');

返回:test: ?_MATH0, test: ?_MATH1

$vars =

array(
[_MATH0] => (2+2)
[_MATH1] => (3*(1+2))
)

希望它有效。对我来说确实如此。如果您在参考中误解了某些内容或发现了错误,请在下面进行评论。 (对于错误 - 如果您了解并测试了解决方案,则进行编辑)