2

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

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

在我的母语中,最多三个级别的引用在印刷上是正确的,每个级别都有自己的引号。我想将所有双引号替换为其对应的实体,例如:

  • 第一级:“文本”(„”
  • 第二级:»text«(»«
  • 第三级:'文本'(’
  • 任何附加级别:'text' ( ’)

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

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

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

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

所以这将输出为:

引用我书中的一句话:“她没有感到“沮丧”、“疲倦”或“悲伤”。”

(这可能很棘手,但我们知道 a"之后或之前总是有空格或标点符号,, ., ;, ?, !

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

$str = '<p class="quote">The error said: <span class="error_msg">"Please restart your "fancy" computer!"</span></p>';

我听说使用递归正则表达式可能是一种解决方案,但我正在寻找一种更有效的方法,因为字符串可能是长 HTML 文本。

更新:似乎我跳过了 CSS 的quotes属性和<q>元素。这使得内联引号更加优雅。

4

2 回答 2

1

试试这"#\"(([^()]+|(?R))*)\"#"是正则表达式递归

样本

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

如果删除回显注释//,输出将是

 **********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
于 2013-04-08T11:15:38.723 回答
1

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

我已经构建了 JoliTypo\DomDocument,它使用 DOM 加载器(在法语中,我们也有不同的引号层次结构,所以它肯定在我的待办事项列表中。

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

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

于 2013-09-04T15:09:32.333 回答