Php 自定义字符串标记上的复杂正则表达式

Php 自定义字符串标记上的复杂正则表达式,php,regex,string,preg-match,Php,Regex,String,Preg Match,我试图在方括号中的标记之间获取文本 让我们看看简单的字符串示例: 这是一篇法语文本这是一篇英语文本 然后在PHP中(使用): 更复杂的解决方案如何 我的意思是如果没有设置语言->使用默认值(英语)。如果字符串包含标签外的字符串,则沿所选语言显示该字符串。如果字符串不包含所请求的语言->显示默认值(或者如果未设置默认值,则在字符串中首先显示)。示例: $this->language->__set("defLang", "english"); $str = "This is a [fr

我试图在方括号中的标记之间获取文本

让我们看看简单的字符串示例:

这是一篇法语文本这是一篇英语文本

然后在PHP中(使用):

更复杂的解决方案如何

我的意思是如果没有设置语言->使用默认值(英语)。如果字符串包含标签外的字符串,则沿所选语言显示该字符串。如果字符串不包含所请求的语言->显示默认值(或者如果未设置默认值,则在字符串中首先显示)。示例:

$this->language->__set("defLang", "english");

$str = "This is a [french]French text[/french][english]English text[/english]";
$this->language->lang = "french"; 
return $this->language->translate($str);
//OUTPUT: This is a French text

$str = "This is a [deutch]Deutch text[/deutch][english]English text[/english]";
$this->language->lang = "french"; 
return $this->language->translate($str);
//OUTPUT: This is a English text

$str = "This is a [french]French text[/french][deutch]Deutch text[/deutch]";
$this->language->lang = "english"; 
return $this->language->translate($str);
//OUTPUT: This is a French text
使用PHP实现这一点的最佳方法是什么?我怀疑它需要复杂的正则表达式,但由于我不熟悉正则表达式,我想知道是否还有其他方法

编辑:

根据jeff()提供的答案,我制作了在大多数情况下都能工作的函数。谢谢

function translate($text)
{
    $exp = '/(\[(.+?)\])(.+?)\[\/.+?\]/i';
    $m = preg_match_all( $exp, $text, $matches);

    if($m){

        $mtchs = $matches[0];
        $langs = $matches[2];
        $texts = $matches[3];
        $c = 0;
        $foundLang = false;
        $foundFirstOptionalLang = false;

        foreach($langs as $l){
            if($l == $this->lang){
                $text = str_replace($mtchs[$c], $texts[$c], $text);
                $foundLang = true;
            }else{
                if(!$foundFirstOptionalLang && $l == $this->defLang){
                    $optionalText = str_replace($mtchs[$c], $texts[$c], $text);
                    $foundFirstOptionalLang = true;
                }
                $text = str_replace($mtchs[$c], "", $text);
            }
            $c++;
        }
        if (!$foundLang) $text = $optionalText;
    }

    return $text;
}
试试这个:

 function translate($str){
      // If the language has been set use it, otherwise use the default value         
      $lang = isset($this->language->lang)?$this->language->lang:$this->language->defLang;

      if(preg_match("/\[$lang\](.+)\[\/$lang\]/", $str, $m)){
           return $m[1];              
      }else{
           // There was no text found for $lang,  fall back to english         
           preg_match("/\[english\](.+)\[\/english\]/", $str, $m);
           return $m[1];
      }


 }

您可以使用以下内容:

$exp = '/(\[(.+?)\])(.+?)\[\/.+?\]/i';
$str = "This is a [french]French text[/french] and [english]English text[/english]";

$m = preg_match_all( $exp, $str, $matches);
echo "<pre>";
var_dump( $matches);
echo "</pre>";

因此,您可以访问数组[2]作为语言名称,访问数组[3]作为实际文本。

对于这种特殊情况:


这是唯一可能的文本格式吗?它们是否总是彼此相邻,并且在字符串中只有一个集合?不太可能。这些只是字符串外观的示例。这是基本的静态解决方案。不太复杂,因为它的工作方式与我第一个没有正则表达式的示例相同。谢谢。不确定为什么要将其设置为“复杂”如果它有效。它还需要做什么你没有解释的事情呢?它不检查字符串中是否设置了任何lang。2.也不检查字符串中是否设置了默认语言。它不接受标记之外的字符串…不仅仅是“有效”一个特定例子的解决方案我希望有一个通用的解决方案,使它在大多数情况下都能工作。谢谢。是的。投票结果是因为对我的例子来说,它能起作用。但它仍然不是真正复杂的解决方案。谢谢。我可以接受这一点,因为它为以后的工作奠定了良好而清晰的基础。我更新了我的问题,在大多数情况下添加了工作函数,bas谢谢你的回答。
$exp = '/(\[(.+?)\])(.+?)\[\/.+?\]/i';
$str = "This is a [french]French text[/french] and [english]English text[/english]";

$m = preg_match_all( $exp, $str, $matches);
echo "<pre>";
var_dump( $matches);
echo "</pre>";
array(4) {
  [0]=>
  array(2) {
    [0]=>string(28) "[french]French text[/french]"
    [1]=>string(31) "[english]English text[/english]"
  }
  [1]=>
  array(2) {
    [0]=> string(8) "[french]"
    [1]=> string(9) "[english]"
  }
  [2]=>
  array(2) {
    [0]=>string(6) "french"
    [1]=>string(7) "english"
  }
  [3]=>
  array(2) {
    [0]=>string(11) "French text"
    [1]=>string(12) "English text"
  }
}
function getTextInTag($text,$tag='english')
{
    $innerText = preg_replace('#^.*\['.$tag.'\](.+?)\[/'.$tag.'\].*$#','$1',$text);
    if($innerText == $text) $innerText = preg_replace('#^.*\[english\](.+?)\[/english\].*$#','$1',$text);
    $text = preg_replace('#(\[[^\]]+\].+?\[/[^\]]+\])+#','',$text);
    return $text.$innerText;
}

getTextInTag('This is a [french]French text[/french][english]English text[/english]'); //This is a English text
getTextInTag('This is a [french]French text[/french][english]English text[/english]','french'); //This is a French text
getTextInTag('This is a [french]French text[/french][english]English text[/english]','spanish'); //This is a English text