1

I have a CSS file which includes a set of rules wrapped in a @critical rule containing critical styles whose content I want to extract for inlining:

@critical {

    .foo {
        ...
    }

    @media bar {
        ...
    }
}

I’m trying to do the extraction using sed search and replace with the following regex (I’m on a Mac, hence the -E flag):

sed -i '' -E 's,@critical[^{]*{\s*((.|\s)*)[^}]*},\1,g' style.css

Effectively I'm trying to replace the entire @critical rule with only its content (match group 1). The regex critical[^{]*{\s*((.|\s)*)[^}]*} itself works perfectly when I plug it into RegExr but I can’t seem to get it to work in the context of the above sed command. What am I doing wrong?

Thanks very much in advance.

—————

Edit:

I have since learned that sed doesn’t support multiline regex which would explain the problem I’m encountering. While minifying the CSS (effectively turning it into a single line of text) makes it work under sed, I’d still appreciate someone pointing me towards a solution that works across a non-minified multiline CSS file (perl? awk?).

3
  • 2
    Why is people downvoting? Its a legitimate question. Come on! Commented Feb 3, 2020 at 13:58
  • Can you add some samples of the properties instead of the ... ? Commented Feb 3, 2020 at 13:58
  • @Matias Barrios in the meanwhile i have learned that sed doesn’t seem to support multiline regex. this seems to be the cause of error because when i minify the css (effectively turning it into a single line) it works as intended. i’d still prefer a solution that doesn’t require minifying the css for it to work. Commented Feb 3, 2020 at 15:41

1 Answer 1

2

If perl is your option, would you please try:

perl -0777 -i.bak -pe 's,\@critical[^{]*{\s*((.|\s)*)[^}]*},$1,g' style.css

Then style.css will look like:

.foo {
        ...
    }

    @media bar {
        ...
    }

  • The -0777 switch tells perl to slurp all lines at once, which makes the regex match over multiple lines.
  • The -i.bak option enables an in-place file editing keeping the backup file with .bak extension. If no backup is needed, just put -i.
  • The regex inside is almost identical to yours except for a backslash before the at-mark. Otherwise perl tries to interpret it as an array variable name. Another change is the $1 instead of \1 in the replacement. This is also the perl's requirement.
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for sharing it, is there any book you could lemme know which has perl one liners kind of, I tried to google but mostly have deep in perl, right now I am looking for one liners only from basics, if anything you could share will be grateful to you, cheers :)
How about a page here or a book here. Perl has so many command-line options that I imagine there will be nobody in the world who have tried all of them (except for Larry Wall and Tom Christiansen). Cheers!
Woww, cool. Thank you lemme go through it thanks a TON for letting know here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.