转换字符串,但用大括号括起来的字符

时间:2018-10-17 17:43:33

标签: php regex preg-replace preg-replace-callback

  1. 我正在转换用户输入的字符串(成功,但是...)
  2. 我想忽略花括号中的字符
  3. 也请删除最终输出中的括号

例如,如果我有这个字符串:

$string = "[ABC] This & Text";

function make_post_type($string) {
  $needle   = array('-', ' ');
  $clean    = preg_replace("/[^a-zA-Z0-9_\s]/", "", strtolower($string)); // Remove special characters
  $haystack = preg_replace('!\s+!', ' ', $clean); // Now remove extra spaces

  return str_replace($needle, '_', $haystack);
}

返回abc_this_text

我想退回ABC_this_text

4 个答案:

答案 0 :(得分:2)

您可以在preg_replace_callback中使用此正则表达式代码:

function replc($str) {
   return preg_replace_callback (
      '/\[([^]]*)\]|{([^}]*)}|([^][{}]+)/',
      function ($m) {
         return (isset($m[1])?$m[1]:"") .
                (isset($m[2])?$m[2]:"") .
                 (isset($m[3]) ?
                 preg_replace('/\W+/', '_', strtolower($m[3])) : "");
      },
      $str
   );
}

呼叫为:

echo replc( "[ABC] This & Text" );
ABC_this_text

echo replc( "abc.Xyz {PQR} Foo-Bar [ABC] This & Text" );
abc_xyz_PQR_foo_bar_ABC_this_text

第一个RegEx详细信息:

  • [([^]]*)\]:如果遇到[...],请捕获#1组的内部
  • |:或
  • {([^}]*)}:如果遇到{...},则捕获#2组的内部
  • |:或
  • [^][{}]+:匹配不是[]以及{}的1+个字符,并捕获到#3组中

第二个RegEx:

  • \W+:匹配1个以上的非单词字符,并替换为_

答案 1 :(得分:1)

一种解决方案是将字符串分成单词数组。
如果单词仅包含Base.Document.Current.FreightTaxCategoryID = null; Base.Document.Update(Document.Current); sender.SetDefaultExt<SOOrder.freightTaxCategoryID>(e.Row); ,则将其删除,否则请使用特殊字符和strtolower来完成所有其他操作。

然后内爆回到字符串并返回

[]

https://3v4l.org/rZlaP

答案 2 :(得分:1)

您可以使用preg_match_all并使用2个捕获组。

\[([A-Z]+)\]|(\w+)

使用array_reduce来检查索引中的归拢组,最后使用下划线将其内爆:

例如:

$re = '/\[([A-Z]+)\]|(\w+)/';
$string = "[ABC] This & Text";
preg_match_all($re, $string, $matches, PREG_SET_ORDER, 0);

echo implode('_', array_reduce($matches, function($carry, $item){
    if ($item[1] === "") {
        $carry[] = strtolower($item[2]);
        return $carry;
    }
    $carry[] = $item[1];
    return $carry;

})); //ABC_this_text

说明

  • \[([A-Z]+)\]匹配[,在一个组中捕获1个以上大写字符,并匹配]。要匹配括号之间的所有内容,可以改用\[([^]]+)\]
  • |
  • (\w+)捕获1个以上单词字符。如果要匹配的内容超过\w,则可以使用字符类并添加要匹配的内容,例如[\w!?]+

Regex demo | Php demo

答案 3 :(得分:1)

您可以通过以另一种方式查看问题来减少生成所需字符串的步骤。首先匹配您需要的内容,然后在末尾用_替换空格和破折号:

function make_post_type($s) {
    preg_match_all("~({[^{}]*}|\[[^][]*])|[\w\s]+~", $s, $m);
    $s = '';
    foreach($m[0] as $k => $v) {
        $s .= $m[1][$k] ? substr($v, 1, -1) : strtolower($v);
    }
    return preg_replace('~[-\s]+~', '_', $s);
}

我将{[^{}]*}|\[[^][]*]括在圆括号中,以便以后可以检查(bool) $m[1][$k],该变量告诉$m[1]返回的捕获组中是否存在迭代中的当前值,然后剥离一个前导和尾随字符从字符串。

请参见live demo here