所以我是一个排版纳粹分子(他们就像打了类固醇的语法纳粹分子),并且我有一个字符串,其中可能包含多级双引号,例如:
$str = 'Outer text "first level "second level "third level" second level" first level" outer text';
在我的母语中,最多三级引用在打印上是正确的,每个级别都有自己的引号。我想替换所有双引号对为其相应的实体,例如:
- 第一级:“文本”(
„
和”
) - 第 2 级:“文本”(
»
和«
) - 第三级:“文本”(
’
) - 任何其他级别:“文本”(
’
)
所以上面的文本将输出为:
Outer text „first level »second level ’third level’ second level« first level” outer text
此外,可能有 sibling ""
字符串中的对:
$str = 'Quote from my book: "She didn\'t feel "depressed", "tired" or "sad"."';
所以这将输出为:
Quote from my book: „She didn't feel »depressed«, »tired« or »sad«.”
(这可能很棘手,但我们知道 "
后面或前面总是有空格 或标点符号
,
、 .
、 ;
、 ?
、 !
)
最后,$str
也可能包含 HTML,其中属性的引号不应更改:
$str = '<p class="quote">The error said: <span class="error_msg">"Please restart your "fancy" computer!"</span></p>';
我听说使用递归正则表达式是一种可能的解决方案,但我正在寻找一种更有效的方法,因为字符串可能是很长的 HTML 文本。
更新:我似乎忽略了 CSS 的 quotes
属性(property)和<q>
元素。这使得内联引号更加优雅。
最佳答案
试试这个 "#\"(([^()]+|(?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 '„'.$Query.'”';
case 2:
return '»'.$Query.'«';
case 3:
return '’'.$Query.'’';
default:
return '’'.$Query.'’';
}
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 '„'.$Query.'”';
case 2:
return '»'.$Query.'«';
case 3:
return '’'.$Query.'’';
default:
return '’'.$Query.'’';
}
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 View
Outer text „first level »second level ’third level’ second level« first level” outer text
如果删除 echo 注释//
输出将为
**********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 „first level »second level ’third level’ second level« first level” outer text
关于php - 替换字符串中的嵌套双引号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15877216/