【问题标题】:Using preg_replace to reformat money amounts in text with PHP使用 preg_replace 用 PHP 重新格式化文本中的金额
【发布时间】:2021-01-14 23:45:08
【问题描述】:

我正在为一些正则表达式而苦苦挣扎。我想要做的是在字符串中查找金额,删除€,$或£但保留数字,然后查看是否有'b'或'm' - 在这种情况下写'百万铂金币”或“百万金币”,否则就放“金币”。

我的大部分内容都是 hack(见下文),我的正则表达式似乎不起作用的小问题。金额不变。

期望的行为示例

我打算保留小数位和千位分隔符

1260 万美元 ==> 1260 万金币

£2b ==> 200 万铂金币

99 欧元 ==> 99 金币

我的代码

这是我的非工作代码(我怀疑我的正则表达式可能是错误的)。

protected function funnymoney($text){
    $text = preg_replace('/[€$£]*([0-9\.,]+)([mb])/i','\0 %\1%',$text);
    $text = str_replace('%b%','million platnum coins',$text);
    $text = str_replace('%m%','million gold coins',$text);
    $text = str_replace('%%','gold coins',$text);
    return $text;
}

如果有人能向我解释我缺少什么或出错并指导我找到正确的答案,我将不胜感激。你可以放心地假设我对正则表达式知之甚少。如果可以的话,我想了解为什么该解决方案也有效。

【问题讨论】:

    标签: php regex preg-replace


    【解决方案1】:

    使用preg_replace_callback,您可以在单个函数调用中执行此操作:

    define ("re", '/[€$£]*(\.\d+|\d+(?:[.,]\d+)?)([mb]|)/i');
    
    function funnymoney($text) {
       return preg_replace_callback(re, function($m) {
          return $m[1] .
            ($m[2] != "" ? " million" : "") . ($m[2] == "b" ? " platinum" : " gold") .
            " coins";
       }, $text);
    }
    
    // not call this function
    
    echo funnymoney('$12.6m');
    //=> "12.6 million gold coins"
    
    echo funnymoney('£2b');
    //=> "2 million platinum coins"
    
    echo funnymoney('€99');
    //=> "99 gold coins"
    

    【讨论】:

      【解决方案2】:

      我不确定您打算如何处理小数位和千位分隔符,因此我的部分模式可能需要调整。除此之外,匹配前导货币符号(以便使用/删除它,然后捕获数字子字符串,然后捕获可选的尾随单位(bm)。

      使用查找数组将单位翻译成英文。当缺少单位字符时,应用查找数组中的后备值。

      查找数组将使您的任务更易于阅读和维护。

      代码:(Demo)

      $str = '$1.1m
      Foo
      £2,2b
      Bar
      €99.9';
      
      $lookup = [
          'b' => 'million platinum coins',
          'm' => 'million gold coins',
          ''  => 'gold coins',
      ];
      
      echo preg_replace_callback(
               '~[$£€](\d+(?:[.,]\d+)?)([bm]?)~iu',
               function($m) use ($lookup) {
                   return "$m[1] " . $lookup[strtolower($m[2])];
               },
               $str
           );
      

      输出:

      1.1 million gold coins
      Foo
      2,2 million platinum coins
      Bar
      99.9 gold coins
      

      【讨论】:

      • 我选择了这个答案,因为如果我在长时间休息后返回我的代码,它最有可能让我稍后修改它并理解它。此外,它就像一个魅力。
      【解决方案3】:

      您的正则表达式在字符串上有第一个完全匹配,它在返回数组的索引 0 上,但您似乎只需要捕获组。

      $text = preg_replace('/[€$£]*([0-9\.,]+)([mb])/i','\1 %\2%',$text);
      

      有趣的问题,顺便说一句!

      【讨论】:

      • 谢谢,当我为自己的娱乐编写代码时,我会做一些奇怪的事情。如果您想查找我,我会在某个时候将最终结果放到网上。
      【解决方案4】:

      这是你想要的吗?

      <?php
      
      /**
          $12.6m ==> 12.6 million gold coins
      
          £2b ==> 2 million platinum coins
      
          €99 ==> 99 gold coins
       */
      
      $str = <<<EOD
      $12.6m
      
      £2b
      
      €99
      EOD;
      
      preg_match('/\$(.*?)m/', $str, $string1);
      echo $string1[1] . " million gold coins \n";
      
      preg_match('/\£(.*?)b/', $str, $string2);
      echo $string2[1] . " million platinum coins \n";
      
      preg_match('/\€([0-9])/', $str, $string3);
      echo $string3[1] . " gold coins \n";
      
      // output:
      // 12.6 million gold coins
      // 2 million platinum coins
      // 9 gold coins
      

      【讨论】:

      • 不像我在寻找 9 种可能的组合。但是,如果有点不雅,您的一般方法很可能会奏效。
      猜你喜欢
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 2023-03-21
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 2011-11-26
      相关资源
      最近更新 更多