1

I'm struggling to match and keep all CSS rules containing the string 224,13,78.

Sample input:

h1 {
    color: rgb(224,13,78);
}


h1 {
    display: block; /* Delete this whole block */
}


#test-color {
    color: rgb(224,13,78);
}    


.test-position {
    position: absolute; /* Delete this whole block */
}


.test-bg-color {
    background-color: rgba(224,13,78,0.5);
}


@media ( max-width: 1200px ) {
    .test-color {
        color: rgb(224,13,78);
    }

    .test-position {
        overflow: hidden; /* Delete this whole block */
    }
}

Desired output:

h1 {
    color: rgb(224,13,78);
}


#test-color {
    color: rgb(224,13,78);
}


.test-bg-color {
    background-color: rgba(224,13,78,0.5);
}


@media ( max-width: 1200px ) {
    .test-color {
        color: rgb(224,13,78);
    }
}

Is there a handy regex that solves my problem?

For reference, I found this solution, but it matches the property name, not the value:

Find: \{.*(font-size\:\s*\d+px\;).*\}?

Replace: \{ $1 \}

And also this JavaScript solution that does the same:

What is RegEx to remove css keeping font size

I accept a JavaScript solution too, but PHP is preferable.

Thank you all in advance.

Eduardo SR
  • 59
  • 5

1 Answers1

1

Try the following regex:

\h*+[^\s{}][^{}]*{(?:[^{}](224,13,78)?)++[^{}]*+}(?(1)(*SKIP)(*F))\R*

See live demo here

What it does is trying to match a sequence of characters 224,13,78 in a {...} block. If it matches it holds the value in the first capturing group. Then later we say if 1st capturing group was successful in matching, then skip over whatever has been matched by:

(?(1)(*SKIP)(*F))

otherwise the whole match doesn't contain the desired characters and engine won't skip over it. We now only need to replace matched blocks with nothing:

$css = preg_replace('~\h*+[^\s{}][^{}]*{(?:[^{}](224,13,78)?)++[^{}]*+}(?(1)(*SKIP)(*F))\R*~', '', $css);
revo
  • 47,783
  • 14
  • 74
  • 117
  • Excelent @revo, it works, thank you! Do you have a idea to clean any other property inside every matched block and keep only the line containing `224,13,78`? Input: `h1 { position: absolute; color: rgb(224,13,78); display: block; }` Output: `h1 {color: rgb(224,13,78);}` – Eduardo SR Nov 01 '18 at 11:23
  • My pleasure. Just run another `preg_replace` on the previous output with this `\s*[^\s:{}]+:((?!224,13,78)[^;])*+;`. See live demo here https://regex101.com/r/Q9W14l/3 – revo Nov 01 '18 at 11:28
  • 1
    Great, you helped me a lot. Thank you again! – Eduardo SR Nov 01 '18 at 11:36
  • revo can you make the first RegEx also consider line breaks between selectors and delete them? Check here https://regexr.com/42b6t – Eduardo SR Nov 01 '18 at 13:35
  • 1
    Yes, but it will remove leading newline characters as well which makes CSS less readable. Try `\h*[^\s{}][^{}]*{(?:[^}](224,13,78)?)+[^}]*}(?(1)(*SKIP)(*F))\R*` instead. – revo Nov 01 '18 at 13:51
  • I see... it solved, i think the last fix is not to match the opening brace that wraps the block, but limit the match to the selector braces, see: https://regexr.com/42b6t – Eduardo SR Nov 01 '18 at 14:13
  • Nice! The second RegEx, I found it breaks media rules and pseudo elements, see: https://regexr.com/42bd6 – Eduardo SR Nov 01 '18 at 14:42
  • 1
    Replace `[^;]*` with `[^;{}]*`. – revo Nov 01 '18 at 14:47