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.
- 199,887
- 59
- 344
- 454
- 20,305
- 41
- 116
- 158
-
1Does 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
8 Answers
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."
- 6,741
- 2
- 48
- 42
- 199,887
- 59
- 344
- 454
-
10
-
109For linux noobs like me: `sed '/^#/ d' < inputFile.txt > outputFile.txt` – Neil McGuigan Jul 28 '14 at 19:12
-
How can i keep the lines which start with # and delete every other lines i need to remove every contents except which start with # – Babin Lonston Oct 02 '14 at 16:22
-
64
-
18And `sed -i '' '/^#/d' filepath` on Mac ([because the -i suffix is mandatory](http://stackoverflow.com/a/16746032/125246)) – paulcm Aug 05 '16 at 10:44
-
What if I need to replace only the first line starting with a string? – Viesturs Aug 07 '18 at 12:44
-
1@Viesturs Try this: ``awk '/^#/ && !first { first=1 ; next } { print $0}' `` – Raymond Hettinger Aug 10 '18 at 06:39
-
@NeilMcGuigan better make sure `inputFile.txt` is NOT the same as `outputFile.txt` – Larpon Oct 22 '18 at 21:58
-
To apply this to all files matching a shell pattern, use something like this (replace *.txt as needed): `for e in *.txt ; do sed -i '/^#/d' $e ; done` – Per Lundberg Aug 21 '20 at 19:00
-
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).
- 242,098
- 41
- 402
- 602
-
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
The opposite of Raymond's solution:
sed -n '/^#/!p'
"don't print anything, except for lines that DON'T start with #"
- 2,025
- 1
- 14
- 19
-
-
@lacostenycoder It's about the same as any other option presented here, which is enough merit to mention it. – ata Apr 14 '22 at 19:37
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
- 17,707
- 27
- 124
- 213
You can use the following for an awk solution -
awk '/^#/ {sub(/#.*/,"");getline;}1' inputfile
- 71,025
- 22
- 98
- 142
This answer builds upon the earlier answer by Keith.
egrep -v "^[[:blank:]]*#" should filter out comment lines.
egrep -v "^[[: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.
-
Assuming your `egrep` supports that syntax; older versions might not. – Keith Thompson Oct 30 '13 at 17:45
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
- 28,551
- 4
- 47
- 46