需要优化:使用正则表达式使用可选且可重复的模式重新格式化字符串

我想使用正则表达式重新格式化 PHP 中的字符串。

该字符串可以如下所示:(例如)

bj-11_2008-06_2015(F01,F02,F03,F04)
bj-11_2008-06_2015(F01)
bj-11_2008-06_2015(01)
bj-11_2008-06_2015(3B)
bj-11_2008-06_2015bj-11_2008

让我们看一下:

第一部分是强制性的bj-11_2008,并且是bj固定的,11_2008可以是任何格式的日期MM_YYYY
第二部分是可选的-06_2015,同样应该是MM_YYYY
括号也是可选的(3B),但如果有的话,应该至少包含一个条目,但最多包含 n 个条目。
每个条目最多应包含 4 个大写字母和/或数字,并用“,”分隔,例如:(F01,F02,F03,F04)

然后一切都应该像这样重新格式化:

  1. bj-删除

  2. 日期中的下划线“_”替换为竖线“|”

  3. 破折号“-”周围有空格

  4. 第二次日期后的空格

  5. 用。。。来代替 ”;”

输出示例:

11|2008 - 06|2015 (F01;F02;F03;F04)

这是我已经得到的:

正则表达式:

bj-([0-9]{2})_([0-9]{4})[-]*([0-9]{2})?_?([0-9]{4})?([(]([[:alnum:]]{0,4},?)*[)])?

https://regex101.com/r/R7R3jC/1

PHP:

$regex = "/bj-([0-9]{2})_([0-9]{4})[-]*([0-9]{2})?_?([0-9]{4})?([(]([[:alnum:]]{0,4},?)*[)])?/";

$teststrings=array(

        "bj-11_2008-06_2015(F01,F02,F03,F04)",

        "bj-11_2008-06_2015(F01)",

        "bj-11_2008-06_2015(01)",

        "bj-11_2008-06_2015(3B)",

        "bj-11_2008-06_2015",

        "bj-11_2008"

    );


foreach ($teststrings as $teststring) {


    echo preg_replace_callback($regex, function($matches) {

            $regexp2 = "/([[:alnum:]]{0,4},?)/";

            $string ="";

            

            if (isset($matches[5])) {

                $string = "(";

                preg_match_all($regexp2, $matches[5], $inner_matches, PREG_SET_ORDER);

                

                foreach($inner_matches as $match){

                    $string .= "$match[0]";

                }

                $string .= ")";

                $string = str_replace(",",";",$string);

            }

            

            if (isset($matches[4])){

                echo "$matches[1]|$matches[2] - $matches[3]|$matches[4]" . " $string<br>";

            } 

            else {

                echo "$matches[1]|$matches[2]";

            }

        }

    , $teststring);

}

http://sandbox.onlinephpfunctions.com/code/12b77482508f9d41e8b27a8c4df57bf47914155e


这是可行的,但我认为相对复杂,可能可以简化和优化。但这是我用我对正则表达式非常有限的知识所能做出的全部,

你能帮助我吗?


慕田峪4524236
浏览 102回答 2
2回答

largeQ

由于您的原始字符串已经格式化并且此格式是已知的,因此您无需使用正则表达式模式来探索它,您可以通过简单的替换来完成:$s = <<<'EOD'bj-11_2008-06_2015(F01,F02,F03,F04)bj-11_2008-06_2015(F01)bj-11_2008-06_2015(01)bj-11_2008-06_2015(3B)bj-11_2008-06_2015bj-11_2008EOD;$trans = [ 'bj-' => '', '_' => '|', '-' => ' - ', '(' => ' (',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;',' => ';' ];echo strtr($s, $trans);演示

慕桂英4014372

没有任何正则表达式,仅使用一些子字符串:$input='bj-11_2008-06_2015(F01,F02,F03,F04)';$s1=$s2=$s3='';$sub = substr($input,3,7);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // => 11_2008$s1 = str_replace('_','|',$sub);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // => 11|2008$sub = substr($input,11,7);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// => 06_2015if($sub !== false){&nbsp; &nbsp;$s2 = ' - '.str_replace('_','|',$sub); // => - 06|2015&nbsp; &nbsp;}$sub = substr($input,18);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// => (F01,F02,F03,F04)if($sub !== false){&nbsp; &nbsp;$s3 = str_replace(',',';',$sub);&nbsp; &nbsp; &nbsp; &nbsp;// =>&nbsp; (F01;F02;F03;F04)&nbsp; &nbsp;}$result = $s1.$s2.$s3;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // => 11|2008 - 06|2015 (F01;F02;F03;F04)
打开App,查看更多内容
随时随地看视频慕课网APP