263

All of the lines with comments in a file begin with #. How can I delete all of the lines (and only those lines) which begin with #? Other lines containing #, but not at the beginning of the line should be ignored.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
Village
  • 22,513
  • 46
  • 122
  • 163
  • 1
    Does it have to work with the common convention that `#blah \blah` counts as a single "logical line" because the backslash escapes the newline? – sarnold Nov 21 '11 at 01:18
  • @sarnold: apart from `make`, which utilities use the 'backslash splices lines before ending a comment'? The shells (bash and ksh tested) don't. C and C++ do handle newline splicing before other processing of preprocessor directives, but they're directives rather than comments. – Jonathan Leffler Nov 21 '11 at 02:16
  • @Jonathan: Awesome. I had assumed that the common `\` escaping would also work on comments. But wow I was wrong. I haven't been able to find another example yet... :) Thanks! – sarnold Nov 21 '11 at 02:31

10 Answers10

433

This can be done with a sed one-liner:

sed '/^#/d'

This says, "find all lines that start with # and delete them, leaving everything else."

Vlad
  • 7,997
  • 3
  • 56
  • 43
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
73

I'm a little surprised nobody has suggested the most obvious solution:

grep -v '^#' filename

This solves the problem as stated.

But note that a common convention is for everything from a # to the end of a line to be treated as a comment:

sed 's/#.*$//' filename

though that treats, for example, a # character within a string literal as the beginning of a comment (which may or may not be relevant for your case) (and it leaves empty lines).

A line starting with arbitrary whitespace followed by # might also be treated as a comment:

grep -v '^ *#' filename

if whitespace is only spaces, or

grep -v '^[  ]#' filename

where the two spaces are actually a space followed by a literal tab character (type "control-v tab").

For all these commands, omit the filename argument to read from standard input (e.g., as part of a pipe).

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • I have added a [new answer](http://stackoverflow.com/a/19671392/832230) which builds upon this answer. – Asclepius Oct 30 '13 at 16:19
  • I had troubles using grep in this way on Windows. The solution is to replace ' by ", e.g. `grep -v "^#" filename` – Serg Oct 12 '14 at 15:51
22

The opposite of Raymond's solution:

sed -n '/^#/!p'

"don't print anything, except for lines that DON'T start with #"

ata
  • 2,045
  • 1
  • 14
  • 19
14

you can directly edit your file with

sed -i '/^#/ d'

If you want also delete comment lines that start with some whitespace use

sed -i '/^\s*#/ d'

Usually, you want to keep the first line of your script, if it is a sha-bang, so sed should not delete lines starting with #!. also it should delete lines, that just contain only a hash but no text. put it all together:

sed -i '/^\s*\(#[^!].*\|#$\)/d'

To be conform with all sed variants you need to add a backup extension to the -i option:

sed -i.bak '/^\s*#/ d' $file
rm -Rf $file.bak
rubo77
  • 19,527
  • 31
  • 134
  • 226
8

You can use the following for an awk solution -

awk '/^#/ {sub(/#.*/,"");getline;}1' inputfile
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
6

This answer builds upon the earlier answer by Keith.

grep -Ev "^[[:blank:]]*#" should filter out comment lines.

grep -Ev "^[[:blank:]]*(#|$)" should filter out both comments and empty lines, as is frequently useful.

For information about [:blank:] and other character classes, refer to https://en.wikipedia.org/wiki/Regular_expression#Character_classes.

Torito
  • 5
  • 2
Asclepius
  • 57,944
  • 17
  • 167
  • 143
1

You also might want to remove empty lines as well

sed -E '/(^$|^#)/d' inputfile
  • Or `grep -v '^ *\(#.*\|\)$' to remove line containing only spaces or spaces before comments too. – techno Jul 31 '23 at 12:53
1

If you want to delete from the file starting with a specific word, then do this:

grep -v '^pattern' currentFileName > newFileName && mv newFileName currentFileName

So we have removed all the lines starting with a pattern, writing the content into a new file, and then copy the content back into the source/current file.

Aditya Aggarwal
  • 610
  • 6
  • 7
0

Delete all empty lines and also all lines starting with a # after any spaces:

sed -E '/^$|^\s*#/d' inputfile

For example, see the following 3 deleted lines (including just line numbers!):

1. # first comment
2.
3.         # second comment

After testing the command above, you can use option -i to edit the input file in place.

Just this!

Mohsen Abasi
  • 2,050
  • 28
  • 30
-3

Here is it with a loop for all files with some extension:

ll -ltr *.filename_extension > list.lst

for i in $(cat list.lst | awk '{ print $8 }') # validate if it is the 8 column on ls 
do
    echo $i
    sed -i '/^#/d' $i
done
filmor
  • 30,840
  • 6
  • 50
  • 48