【问题标题】:How to get substrings on both sides of hyphen and trailing substring?如何在连字符和尾随子字符串的两侧获取子字符串?
【发布时间】:2017-03-30 03:29:27
【问题描述】:

我目前正在开发一个使用特定字符串来调用函数的网络应用程序。这是一个示例字符串:

$string = "translate from-to word for translate"

首先我需要验证字符串,它应该像上面的$string。我应该如何验证字符串?

然后我需要从$string中提取3个子串。

  • 连字符前面的单词。 (待命名:$target
  • 连字符后面的单词。 (待命名:$source
  • $source 之后到字符串末尾的文本(不包括第一个空格)。 (待命名:$translate

这是我获取fromto 的编码尝试:

$found = false;
$source ="";
$target = "";
$next = 3;
$prev = 1;
for($i=0;$i<strlen($string);$i++){
    if($found== false){
        if($string[$i] == "-"){
            $found = true;
            while($string[$i+$prev] != " "){
                $target .= $string[$i+$prev];
                $prev +=1;
            }
            /*$next -=1;
            while($string[$i-$next] != " " && $next > 0){
                $source .= $string[$i-$next];
                $next -=1;
            }*/
        }
    }
}

从该代码中,我只能在- 之后返回包含to$target
我不知道如何获得$source

请告诉我获取from$sourceto$target 的最快方法。

那我需要得到word for translatefrom-to之后的所有字符串)。

所以结果应该是

$target = "to";
$source = "from";
$translate = "word for translate";

最后,如果$string有两个连字符,比如translate from-to from-to test-test word for translate,应该是return false

注意 tofrom 是随机字符串。

【问题讨论】:

    标签: php string delimiter substring


    【解决方案1】:

    考虑以下可能的输入字符串:

    • translate from-to word for translate(1 个连字符,没有重音符号或非英文字符)
    • translate dari-ke dari-ke word for translate(2 个连字符)
    • translate clé-solution word for translate(1 个连字符,使用重音字符)
    • translate goodbye-さようなら word for translate(1 个连字符,使用日文字符)

    不区分大小写的模式如:/^[a-z]+? ([a-z]+)-([a-z]+?) ([a-z ]+)$/i 将在前两个样本字符串上高效执行请求,但不是最后两个。

    使用“单词字符”(\w)来匹配子字符串(而不是不区分大小写的[a-z])将与前两个样本一样执行,但也允许0-9_ 作为有效字符。这意味着模式准确性会略有下降(这可能对您的项目没有明显影响)。

    如果您要翻译的字符串可能超出英文字符,则使用“否定字符类”进行匹配可能更简单/更宽容。如果您想允许超出a-z 的字母,例如重音字符和其他多字节字符,那么[^-] 将提供广泛的字符余量(代价是也允许许多不需要的字母)。这里是a demo of this kind of pattern

    重要的是只为您想要随后使用的子字符串编写“捕获组”。出于这个原因,我没有捕获前导子字符串translate

    list() 是一种方便的“语言结构”,用于将变量名称分配给数组值。请注意,第一个元素(全字符串匹配)未分配给变量。这就是为什么list() 的参数以, 开头的原因。如果您不想利用 list() 的便利性,那么您可以手动将三个变量名称分配到三行中,如下所示:

    $source=$out[1];
    $target=$out[2];
    $translate=$out[3];
    

    代码:(Demo)

    $strings=[
        "translate from-to word for translate",
        "translate dari-ke dari-ke word for translate",
        "translate clé-solution word for translate",
        "translate goodbye-さようなら word for translate"
    ];
    
    foreach($strings as $string){
        if(preg_match('/^[a-z]+? ([^-]+)-([^-]+?) ([a-z ]+)$/i',$string,$out)){
            list(,$source,$target,$translate)=$out;
            echo "source=$source; target=$target; translate=$translate";
        }else{
            var_export(false);  // $found=false;
        }
        echo "<br>";
    }
    

    输出:

    source=from; target=to; translate=word for translate
    false
    source=clé; target=solution; translate=word for translate
    source=goodbye; target=さようなら; translate=word for translate
    

    虽然 regex 提供了一种更简洁的方法和更少的函数调用,但这是一种非 regex 方法:

    if(substr_count($string,'-')!=1){
        var_export(false);  // $found=false;
    }else{
        $trimmed=ltrim($string,'translate ');
        $array=explode(' ',$trimmed,2);
        list($source,$target)=explode('-',$array[0]);
        $translate=$array[1];
        echo "source=$source; target=$target; translate=$translate";
    }
    

    【讨论】:

      【解决方案2】:

      如果我正确理解您的问题,可以使用regular expression

      <?php
      $string = "translate from-to word for translate";
      $result = preg_match("/^([\w ]+?) (\w+)-(\w+) ([\w ]+)$/", $string, $matches);
      if ($result) {
          print_r($matches);
          $source = $matches[2];
          $target = $matches[3];
          $translate = $matches[4];
      } else {
          echo "No match";
      }
      

      输出:

      Array
      (
          [0] => translate from-to word for translate
          [1] => translate
          [2] => from
          [3] => to
          [4] => word for translate
      )
      

      这是explanation of the regular expression

      【讨论】:

      • 如果字符串translate from-to from-to test-test word for translate它应该返回false,你能帮我吗
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多