【问题标题】:PHP Remove multiple occurrences in string and merge the remainingPHP删除字符串中的多次出现并合并剩余的
【发布时间】:2012-08-07 13:08:41
【问题描述】:

我有一组从 google sketchup 导出的坐标,带有我一直试图用正则表达式去除的额外绒毛。我认为从例如快速获取 3D 绘图非常有趣。 SketchUp 从 .xsi 文件到画布。这是一个变量中的多个数据集实例:

$str = 'SI_NurbsCurve Edge1 {
        1、
        0,
        0,
        4、
        0,0,1,1,
        2、
        870.243,1229.35,143.395,1
        927.537,1323.53,103.842,1
        }

        SI_NurbsCurve Edge2 {
        1、
        0,
        0,
        4、
        0,0,1,1,
        2、
        899.54,1217.88,116.255,1
        870.243,1229.35,143.395,1
        }';

我已尝试使用此正则表达式从多个实例中删除除坐标数据之外的所有内容:

$reg = '#SI_NurbsCurve Edge[^"]* {
        1、
        0,
        0,
        4、
        0,0,1,1,
        2,#';
$rep="";
$str=preg_replace($reg,$rep,$str);

但是,这只会回显在字符串中找到的最后一个坐标集,在本示例中,以下内容仍然存在:

899.54,1217.88,116.255,1
870.243,1229.35,143.395,1

除了我试图去掉每行坐标上出现的最后一个数字“1”,所以整个例子最终看起来像这样:

870.243,1229.35,143.395,
927.537,1323.53,103.842,

899.54,1217.88,116.255,
870.243,1229.35,143.395,

非常感谢您的时间和专业知识!

【问题讨论】:

    标签: php regex


    【解决方案1】:

    您的第一个问题(仅获取最后一个值)可​​能是由以下原因引起的:

    #SI_NurbsCurve Edge[^"]*
    

    您将需要一个非贪婪的正则表达式,或者如果Edge 之后的值只是数字:

    #SI_NurbsCurve Edge[0-9]*
    

    之后,您可以将剩余的每一行的最后两个字符截掉。

    您可能还需要转义 { 字符:\{ 并在每组之后考虑 } 和空格/换行符,因此第一行应该类似于:

    $str = '#(\}\s+)?SI_NurbsCurve Edge[0-9]* \{
    

    请参阅Codepad 上的工作示例(每行的最后 2 个字符除外...)。

    要同时删除每行末尾剩余的,1,您可以将preg_replace 行更改为:

    $str=preg_replace(array($reg, '#,1\r#'),array($rep,"\r"),$str);
    

    这至少适用于Codepad,但可能取决于换行符的编码。

    【讨论】:

    • 哇,非常感谢您的精彩回复!那么我是否必须在正则表达式输出之后去除 1 和空格,否则会影响性能,当谈到为数千组运行它时?
    • @Oliver 您可以使用另一个正则表达式将,1\n 替换为\n(取决于字符串中换行符的类型)。 preg_replace 接受一个数组作为模式,所以你可以一次性完成。
    • 当然有道理,这对我开始使用 PHP 非常有帮助。非常感谢您的帮助@jeroen!
    • @Oliver 我已将修改添加到替换行。
    • 这很有效,同样使用我这里的编码,我只需将所有内容放在以逗号分隔的一行,然后在 javascript 中处理其余部分并将其输出到画布。谢谢!
    【解决方案2】:

    我认为您正在寻找 $str = substr($str,0,-1)

    【讨论】:

    • 确实,这可能是剥离线端的解决方案,谢谢!
    【解决方案3】:

    无论如何,这不是一个完美的解决方案,但是,使用可用的测试数据,以下将返回所需的输出:

    $str = 'SI_NurbsCurve Edge1 {
            1,
            0,
            0,
            4,
            0,0,1,1,
            2,
            870.243,1229.35,143.395,1
            927.537,1323.53,103.842,1
            }
    
            SI_NurbsCurve Edge2 {
            1,
            0,
            0,
            4,
            0,0,1,1,
            2,
            899.54,1217.88,116.255,1
            870.243,1229.35,143.395,1
            }';
    
    function stripExtra( $inElem ){
      return !preg_match( '/^(?:(?:[0124](?:,0,1,1)?\,)|(?:\})|(?:SI_NurbsCurve Edge.+ \{))$/' , $inElem );
    }
    
    $arr2 = array_filter( array_map( 'trim' , explode( "\n" , preg_replace( "/\,1\s+\n/" , ",\n" , $str ) ) ) , 'stripExtra' );
    
    var_dump( $arr2 );
    
    # Returns
    # array(5) {
    #   [7]=>
    #   string(25) "870.243,1229.35,143.395,"
    #   [8]=>
    #   string(25) "927.537,1323.53,103.842,"
    #   [10]=>
    #   string(0) ""
    #   [18]=>
    #   string(24) "899.54,1217.88,116.255,"
    #   [19]=>
    #   string(25) "870.243,1229.35,143.395,"
    # }
    

    遍历解决方案...

    function stripExtra( $inElem ){
      return !preg_match( '/^(?:(?:[0124](?:,0,1,1)?\,)|(?:\})|(?:SI_NurbsCurve Edge.+ \{))$/' , $inElem );
    }
    

    这个函数将匹配一个显示的字符串。根据提供的字符串是否与特定模式匹配,它将返回 true 或 false。这将允许我们在稍后阶段删除不需要的行。此处使用的模式将匹配以下行:

    SI_NurbsCurve Edge1 {
    0,
    1,
    2,
    4,
    0,0,1,1,
    }
    

    注意:仅当这些行没有以一个或多个空格为前缀时,它才会匹配这些行。但是,由于您的最终输出已经去掉了所有空间,所以这没什么大不了的。

    因此,为了便于阅读,我将在这里将我的单行奇观转换为多行,以便更好地解释它。

    $arr2 = preg_replace( "/1\s+\n/" , "\n" , $str );
    

    这将根据要求仅用逗号替换行尾的任何“,1”实例。

    $arr2 = explode( "\n" , $arr2 );
    

    这会根据换行符拆分字符串,创建一个数组,每行形成一个新元素。

    $arr2 = array_map( 'trim' , $arr2 );
    

    这使用 array_map() 函数 (PHP Documentation) 将 trim() 函数 (PHP Documentation) 应用于每个元素,从每个元素中删除任何前导和/或尾随空格。

    $arr2 = array_filter( $arr2 , 'stripExtra' );
    

    还记得我们上面写的那个函数吗?现在我们遍历数组,并测试每个元素。如果它们与上述行不匹配,则将它们保留在数组中。如果它们与上面不需要的行匹配,则从数组中删除该元素。

    【讨论】:

    • 感谢您对 trim() 阶段的详尽解释,不胜感激!
    猜你喜欢
    • 1970-01-01
    • 2011-04-20
    • 2013-10-02
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2021-04-30
    相关资源
    最近更新 更多