【问题标题】:PHP preg_match_all regular expression to get pixel values (with "px") from cssPHP preg_match_all 正则表达式从css获取像素值(带有“px”)
【发布时间】:2018-08-15 01:53:22
【问题描述】:

我正在寻找与 PHP 的 preg_match_all() 函数一起使用的正则表达式,它将为我提供 CSS 文件中的所有 px 值。

例如,如果使用下面的 css,那么预期的结果将是一个数组:

array ( "11px", "0.45px", "11.0005px", "1.1px", "888.888px" )

$pattern 字符串是我目前所拥有的——但是它似乎不起作用。

我尝试使用的逻辑是:小数点前的数字最多4位,小数符号可选,小数点后的数字可选,最多4位,后跟“px”。

$pattern = "/([0-9]{1,4}\.*[0-9]{1,4}*px)/";

$css = '
.some_class {
    font-size: 11px;
    margin-left: 0.45px;
    margin-top:11.0005px;
    border: 1.1px solid blue;
}
.another_class {
    background: rgba(0, 0, 0, 0.2);
    width: 100%;
    color: #012345;
    z-index: 12;
    font-size: calc(100% + 888.888px);
}
';
preg_match_all($pattern, $css, $matches, PREG_PATTERN_ORDER);

【问题讨论】:

    标签: php css regex preg-match-all pixels


    【解决方案1】:
    • 捕获组是不必要的,只会减慢正则表达式引擎的速度。
    • \b 将确保仅匹配完整的合格号码
    • \d[0-9] 的较短语法。
    • 要匹配零或其中之一,请使用?* 表示零个或多个。
    • 由于并非所有像素值都是浮点数 (11px),因此您可以通过将小数位数字和尾随一到四位数字包装在非捕获组中并添加零或一量词 (?) .
    • 您的模式被打破了,因为您使用了两个连续的量词:{1,4}*,这就像说“匹配 1 到 4 0 次或更多次出现”。正则表达式引擎就像:“嗯?”

    代码:(Demo) (Pattern Demo)

    $css = '
    .some_class {
        font-size: 11px;
        margin-left: 0.45px;
        margin-top:11.0005px;
        border: 1.1px solid blue;
    }
    .another_class {
        background: rgba(0, 0, 0, 0.2);
        width: 100%;
        color: #012345;
        z-index: 12;
        font-size: calc(100% + 888.888px);
    }';
    $pattern = "/\b\d{1,4}(?:\.\d{1,4})?px/";
    
    var_export(preg_match_all($pattern, $css, $matches) ? $matches[0] : 'fail');
    

    输出:

    array (
      0 => '11px',
      1 => '0.45px',
      2 => '11.0005px',
      3 => '1.1px',
      4 => '888.888px',
    )
    

    具有更高验证的模式:

    • 检查 1-4 位数字前面是否有冒号或空格(\K 重新开始全字符串匹配):

      /[: ]\K\d{1,4}(?:\.\d{1,4})?px/
      
    • 检查 1-4 位数字前面没有数字:

      /\D\K\d{1,4}(?:\.\d{1,4})?px/
      

    您的示例输入在小数点前使用零。如果零是可选的,我的模式将需要调整。这些将允许没有前导数字的浮点数,同时要求该点后面有一个数字。

    1. /\D\K(?:\d{1,4}|\d{0,4}\.\d{1,4})px/

    2. /\D\K\d{0,4}(?:\.(?=\d))?\d{1,4}px/

    【讨论】:

    • 嗨,我认为你的回答太棒了!只有一个问题:您注意到如果零是可选的,那么模式将需要调整。事实证明,有一些样式,例如: font-size: .5px 你能澄清一下如何调整它以考虑到这一点吗?谢谢!!
    • 等一下。我会调整的。
    • 我猜第一个“{1,4}”会改成“{0,4}”,对吗?
    • 这会起作用,但它也会匹配px(没有前导数字)虽然这是一个边缘情况。也许对您的项目没有任何影响。
    • 我也可以想象 digit 和 px 之间的空间,但 OP 没有提到这一点。很好的解释和广泛的答案。
    【解决方案2】:

    刚刚对您的模式进行了更正,

    $pattern = "~([0-9]{1,4})px|([0-9]{1,4}?\.[0-9]{1,4})px~";
    
    $css = '
    .some_class {
        font-size: 11px;
        margin-left: 0.45px;
        margin-top:11.0005px;
        border: 1.1px solid blue;
    }
    .another_class {
        background: rgba(0, 0, 0, 0.2);
        width: 100%;
        color: #012345;
        z-index: 12;
        font-size: calc(100% + 888.888px);
    }
    ';
    preg_match_all($pattern, $css, $matches, PREG_PATTERN_ORDER);
    

    $matches中的数据:

    array (
      0 => 
      array (
        0 => '11px',
        1 => '0.45px',
        2 => '11.0005px',
        3 => '1.1px',
        4 => '888.888px',
      ),
      1 => 
      array (
        0 => '11',
        1 => '',
        2 => '',
        3 => '',
        4 => '',
      ),
      2 => 
      array (
        0 => '',
        1 => '0.45',
        2 => '11.0005',
        3 => '1.1',
        4 => '888.888',
      ),
    

    )

    【讨论】:

    • @mickmackusa 您如何/发现什么不正确/不准确?
    • @mickmackusa 我同意你的观点并更新了答案。
    • 您使用了太多的捕获组,这会产生不必要的输出数组膨胀并花费更多步骤。您的模式将匹配 5 位或更多位数字的最后四位数字。 {1,4} 之后的懒惰 ? 并没有什么不同。管道成本步骤,您的模式不是很干燥。 (现在离开我的电脑)
    • 我看不出这个答案有什么更正确的,而且它没有任何解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多