gazjoy
gazjoy

Reputation: 13

How can I extract a hexadecimal value from a range of CSS declarations with REGEX php

So I am trying to echo some hex values from a CSS file with php, but I only want the hex for each of the CSS declarations. I only want to return the ones that are within the declarations containing the .u-fill- not .red

Example CSS:

.red {
    background-color: #ff0000 !important; }

.u-fill-grey-darker {
    background-color: #222 !important; }

.u-fill-grey-dark {
    background-color: #444 !important; }

.u-fill-grey-light {
    background-color: #999 !important; }

I'd like this php to give me a list of hexs from the CSS file like so:

#222
#444
#999

So far I can match all the values using regex like so:

[#\s\d]

But I'd like to do this in a php foreach loop. Is this even possible?!

My php so far looks like this:

<?php
$path = realpath(dirname(__FILE__) . '/../build/css/styles.css');
$css_contents = file_get_contents($path, true);
$lines = explode("\n", $css_contents);
?>
<div>
<?php foreach($lines as $line) :?>
    <?php if($string = substr(trim($line), 0, 7) == '.u-fill') : ?>
        <?php echo $string; ?>
    <?php endif; ?>
<?php endforeach; ?>
</div>

Expected output

<div>#222</div>
<div>#444</div>
<div>#999</div>

This however doesnt work and I dont know where to put the regex and which regex to use. Any help will be muchly appreciated.

Upvotes: 1

Views: 46

Answers (2)

Jeff Puckett
Jeff Puckett

Reputation: 40861

your class is anything that starts with .u-fill-

/.u-fill-/

escape the literal period \.

/\.u-fill-/

ends with one or more characters .+

/\.u-fill-.+/

non-capturing group including newlines (?s:)

/(?s:\.u-fill-.+)/

but don't be greedy +?

/(?s:\.u-fill-.+?)/

Now for the actual value, we'll need a capturing group ()

/(?s:\.u-fill-.+?)()/

we know it will begin with a hash # numbers \d at least one or more +

/(?s:\.u-fill-.+?)(#\d+)/

This is enough to satisfy your given example. But we can do better knowing that CSS can have letters [A-F] besides just numbers.

/(?s:\.u-fill-.+?)(#[\dA-F]+)/

And let's make sure that's a case-insensitive comparison (?i:)

/(?s:\.u-fill-.+?)(?i:(#[\dA-F]+))/

So finally we're left with:

$css_contents = file_get_contents($path, true);

preg_match_all('/(?s:\.u-fill-.+?)(?i:(#[\dA-F]+))/', $css_contents, $matches);

foreach($matches[1] as $match) {
    echo "<div>$match</div>\n";
}

<div>#222</div>
<div>#444</div>
<div>#999</div>

Upvotes: 0

Max
Max

Reputation: 891

You could easily use a regex for that :

$path = realpath(dirname(__FILE__) . '/../build/css/styles.css');
$css_contents = file_get_contents($path, true);

$matches;
preg_match_all('/\.u-fill-.*\n.*(#[0-9a-fA-F]+)/', $css_contents, $matches);

foreach($matches as $match) {
    echo '<div>' . $match . '</div>';
}

Upvotes: 1

Related Questions