1

I'm writing a script that will remove comments from normalize.css which looks like this:

/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */

/* Document
   ========================================================================== */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in
 *    IE on Windows Phone and in iOS.
 */

html {
  line-height: 1.15; /* 1 */
  -ms-text-size-adjust: 100%; /* 2 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/* Sections
   ========================================================================== */

/**
 * Remove the margin in all browsers (opinionated).
 */

I tried with

#!/usr/bin/env sh

normalize="node_modules/normalize.css/normalize.css"
if [[ -f "$normalize" ]]; then
  grep -v "\\/\\*([^*]|[\\r\\n]|(\\*+([^*\\/]|[\\r\\n])))*\\*\\/+" $normalize > index.css
else
  echo "There is no normalize.css available."
fi

I have loaded the normalize.css via package.json

{
  "devDependencies": {
    "normalize.css": "latest"
  }
}

You can test this by saving the above package.json in a folder and running npm i. If you have node and npm you should have node_modules folder with normalize in it.

The regex101 finds the comments with above regex, but grep just outputs the same file with comments.

What am I doing wrong?

EDIT: Expected output:

html {
  line-height: 1.15;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}
6
  • At first glance, it seems like sed would be much better suited for your problem. You could replace everything that matches ^\/\**\*\/$ with '' Commented Jan 19, 2018 at 15:17
  • 3
    is there a particular reason you want to do it with bash and not a minifier via a task runner (grunt, gulp)? Commented Jan 19, 2018 at 15:18
  • But sed works line by line, so the regex would have to take every possible case in the account, no? Commented Jan 19, 2018 at 15:18
  • I need to transform the 'comentless' code some more down the line, so I am using bash, it's quick and relatively easy :) Commented Jan 19, 2018 at 15:19
  • 1
    Added the expected output Commented Jan 19, 2018 at 15:44

1 Answer 1

1

You can use this awk command to remove all css comments that start with /* and end with */:

cat remComm.awk

function remComm() {
   if ( !m )
      m = index($0, cs);

   if ( m && p = index($0, ce) ) {
      $0 = substr($0, 1, m-1) substr($0, p+2);
      if (m = index($0, cs))
         remComm();
   }
}
BEGIN {
   cs="/*";
   ce="*/";
   m = 0;
}
{
   remComm();
   if ( !m && NF )
      print;
}

Use it as:

awk -f remComm.awk normalize.css

Output:

html {
  line-height: 1.15;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}
  • This is non regex solution so should process big files faster.
  • This also takes care of nested comments and presence of multiple comment block per line.
  • We set start position of comment when we encounter /* and get end position when get */ in the file.
  • Using substring functions we strip off commented positions and leave rest in $0
  • function remComm is called recursively to remove multiple comments per line.
  • Using !NF we skip printing blank or whitespace lines.
Sign up to request clarification or add additional context in comments.

5 Comments

The first version worked, the second one fails on the cat remComm.awk command (cat: remComm.awk: No such file or directory)
No no, you have to copy/paste given below cat script and save it as remComm.awk. Then run the awk command as shown.
Oh I see. And what is the benefit of that over the first solution?
This updated script also removes multiple comment block per line.
Awesome! Thank you!

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.