替换字符串中的嵌套双引号

时间:2013-04-08 10:48:33

标签: php regex typography

所以我是一个排版 - 纳粹(他们就像类固醇的语法 - 纳粹),我有一个字符串,可能包含多级双引号,例如:

$str = 'Outer text "first level "second level "third level" second level" first level" outer text';

以我的母语,最多三个级别的引用在印刷上是正确的,每个级别都有自己的引号。我想替换所有双引号到相应的实体,这样:

  • 第1级:“文字”(„”
  • 第二级:»文字«(»«
  • 第3级:'text'(’
  • 任何其他级别:'text'(’

所以上面的文字将输出为:

  

外部文本“第一级”第二级“第三级”第二级“第一级”外部文本

此外,字符串中可能存在兄弟""对:

$str = 'Quote from my book: "She didn\'t feel "depressed", "tired" or "sad"."';

所以这将输出为:

  

从我的书中引用:“她感觉不舒服”,“累了”或“悲伤”。“

(这可能很棘手,但我们知道"始终跟随或前面有空格,或标点符号,.,{{1} },;?

最后,!也可能包含HTML,其中不应更改属性的引号:

$str

我听说使用 recursive regexp 是一种可行的解决方案,但我正在寻找更强大的有效方式,因为字符串可能是长HTML文本。< / p>

更新: 我似乎滑过了CSS的$str = '<p class="quote">The error said: <span class="error_msg">"Please restart your "fancy" computer!"</span></p>'; 属性和quotes元素。这使得内联引号更加优雅。

2 个答案:

答案 0 :(得分:1)

试试这个"#\"(([^()]+|(?R))*)\"#"是regex recursive

样品

class Replace1{
   public $Out,$Depth=0;
   function __construct($Query){
        $this->Depth=0;
        $this->Out=$this->Reaplce($Query);  
   }
   function Reaplce($Query){
      //echo "**********".$Query.$this->Depth."\n";
       $Query = preg_replace_callback("#\"(([^()]+|(?R))*)\"#",function($m){
             $this->Depth++;
             $R=$this->Reaplce($m[1]);
             $this->Depth--;
            return $R;
        },$Query);  
        switch($this->Depth){
          case 0:
             return $Query;
          case 1:
             return '&bdquo;'.$Query.'&rdquo;';
          case 2:
             return '&raquo;'.$Query.'&laquo;'; 
          case 3:
             return '&rsquo;'.$Query.'&rsquo;';  
          default:
             return '&rsquo;'.$Query.'&rsquo;';                     
        }
        return $Query;

  }


}
$obj=new Replace1('Outer text "first level "second level "third level" second level" first level" outer text');
echo $obj->Out;

老php

function R($m){
        Replace1::$Depth++;
        $R=Replace1::Reaplce($m[1]);
        Replace1::$Depth--;
        //echo "***".$R.$this->Depth."\n";
        return $R;
}
class Replace1{
public static $Out,$Depth=0;

    function __construct($Query){
    self::$Depth=0;
    self::$Out=self::Reaplce($Query);   
}

static function Reaplce($Query){
    //echo "**********".$Query.$this->Depth."\n";

    $Query = preg_replace_callback("#\"(([^()]+|(?R))*)\"#","R",$Query);
    //echo "**********".$Query.$this->Depth."\n";   
    switch(self::$Depth){
        case 0:
           return $Query;
        case 1:
           return '&bdquo;'.$Query.'&rdquo;';
        case 2:
           return '&raquo;'.$Query.'&laquo;'; 
        case 3:
           return '&rsquo;'.$Query.'&rsquo;';  
        default:
           return '&rsquo;'.$Query.'&rsquo;';         


    }
    return $Query;

}


}
$obj=new Replace1('Outer text "first level "second level "third level" second level" first level" outer text');
echo Replace1::$Out;

输出

Outer text „first level »second level ’third level’ second level« first level” outer text

html视图

Outer text &bdquo;first level &raquo;second level &rsquo;third level&rsquo; second level&laquo; first level&rdquo; outer text

如果删除echo comment //,则输出将为

 **********Outer text "first level "second level "third level" second level" first level" outer text0
 **********first level "second level "third level" second level" first level1
 **********second level "third level" second level2
 **********third level3
 Outer text &bdquo;first level &raquo;second level &rsquo;third level&rsquo; second level&laquo; first level&rdquo; outer text

答案 1 :(得分:1)

解析HTML来做这种智能引用即使不是不可能,也是一项非常棘手的任务。

我有构建JoliTypo,它使用DOM加载器(\DomDocument),并处理所有文本字符串以对其应用一些排版修复:EnglishQuotes是其中之一,但它只处理第一级此时此刻。在法语中我们也有不同的引号层次结构,所以它肯定在我的待办事项列表中。

虽然@mohammad解决方案适用于简单的字符串,但与JoliTypo相结合,您可能有机会以可靠的方式获得您想要的大型HTML文档。

我可以询问在哪种语言环境中使用这种引用(Outer text „first level »second level ’third level’ second level« first level” outer text)?