44

I'd like to know if there is a way that I could cat file like php.ini and remove all lines starting with ;

For example, if the file contained this:

; - Show all errors, except for notices ; ;error_reporting = E_ALL & ~E_NOTICE ; ; - Show only errors ; ;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR ; ; - Show all errors except for notices ; error_reporting = E_ALL & ~E_NOTICE 

and I ran the correct command cat | {remove comments command}, then I would end up with:

error_reporting = E_ALL & ~E_NOTICE 

Note - I assumed that cat would be the best way to do this but I'm actually fine with the answer using another utility like awk, sed, egrep, etc.

4
  • What about something like error_reporting = E_ALL & E_NOTICE ; Show all errors, except for notices? Should the comment be removed in that case as well? Commented Dec 7, 2011 at 8:29
  • @MichaelKjörling - I'm really fine with just lines starting with comments being removed Commented Dec 7, 2011 at 14:16
  • 2
    cat is the tool to concatenate files. grep is the tool to filter lines based on patterns. sed and awk can also modify those lines. Commented Jan 28, 2013 at 12:32
  • Use less command and search for non-comment lines with &/^[^;] Commented Sep 24, 2024 at 17:12

12 Answers 12

47

You don't need to pipe a file thru grep, grep takes filename(s) as command line args.

grep -v '^#' file1 file2 file3 

will print all lines EXCEPT those that begin with a # char. you can change the comment char to whatever you wish.

If you have more than one comment char (assuming its at the beginning of a line)

egrep -v '^(;|#|//)' filelist 
3
  • 3
    Another one I've done that always stuck with me was grep '^[^;]' filename. I can't speak to its portability though! Commented Dec 8, 2012 at 13:57
  • @JodieC, that's portable but also removes empty lines (Which is often desired). The standard equivalent of egrep is grep -E. One can also use grep -ve '^[;#]' -e '^//' Commented Jan 28, 2013 at 12:30
  • 2
    if you want to remove blank lines, and also line with spaces before the '#' you can do: grep -ve '\s*#' -e '^$' filename Commented Jun 9, 2023 at 18:43
37

You can use:

sed -e '/^;/d' php.ini 
0
10

egrep can save you the use of cat. In other words, create less processes (egrep vs cat+egrep) and use less buffers (pipe from cat to egrep vs no pipe).

It is generally a good idea to limit the use of cat if you simply want to pass a file to a command that can read it on its own.

With this said, the following command will remove comments, even if they are indented with spaces or tabs:

egrep -v '^[[:blank:]]*;' file.ini
2
  • 1
    Funny that you combine the newer [[ character class ]] regex format with the use of the egrep command deprecated for at least a decade or so. Commented Mar 13, 2014 at 16:25
  • Interesting... current docs at gnu.org/software/grep/manual/html_node/… include POSIX classes. Commented Aug 18, 2017 at 12:08
9
egrep -v '^;|^$' $file 

that will exclude lines that begin with the ';', and empty lines.

in regex, ^ indicates the beginning of a line, and $ the end of a line, so ^$ specifies lines where the start of line character and the end of line character are right next to each other.

6
  • so if i'm reading this right this can remove commented lines, but also blank lines? Commented Dec 7, 2011 at 5:26
  • 1
    @cwd Yes. I'm not sure why he included both, but if you only want to remove commented lines just use egrep -v '^;' Commented Dec 7, 2011 at 5:44
  • 4
    egrep likes files too (less processes and buffers used), and a little bonus would be to remove indented comments too: egrep -v '^[[:blank:]]*;' file.ini Commented Dec 7, 2011 at 6:55
  • 10
    We need a "useless use of cat" badge. Commented Dec 7, 2011 at 11:02
  • @nrolans - looks like a popular comment, why not make it an answer? Commented Dec 7, 2011 at 14:13
4
grep -Ev ^'(#|$)' file.txt 

Strips all comments and empty lines from file.txt

Updated answer per Yokai's comment. "Direct invocation as either egrep or fgrep is deprecated, but is provided to allow historical applications that rely on them to run unmodified." ref: https://www.gnu.org/software/grep/manual/grep.html

4
  • 2
    You should consider expanding your answer with a little more information for the uninitiated (e.g., exactly what the regex you use does). Commented Jul 26, 2014 at 21:01
  • 1
    egrep is depreciated. Use grep -Ev instead. Commented Jan 11, 2018 at 8:20
  • 1
    This is the tightest, most elegant answer. Thanks Nikola! Commented Mar 26, 2022 at 10:14
  • A +1 comment from me for a reason: This is not only the tightest, most elegant answer, it's also memorable, expandable, and reasonable. The intention of removing comments is not hunting comment characters for sport, but to get rid of verbose section headers, irrelevant option lines and useless white space. This fits the purpose perfectly. A comment after a command/option won't disturb in 99% of cases, the contrary is true: It is helpful to read the output. Commented Oct 14 at 6:35
3

An elaboration on @shabunc's answer, this uses Perl to strip comments (including inline comments), then print any lines containing anything other than whitespace.

$ perl -ne 's/;.*//; print if /\S/' data.txt 

Explanation:

  • s/;.*// uses the substitution operator (s/<regex>/<replacement>/) to replace instances of a semi-colon and everything following it on a line with the empty string.
  • print if /\S/ prints the line if it matches the regexp \S, which is a character class matching all non-whitespace characters.
1
  • Does this cause problems with lines that contain an internal ; semicolon? Don't you want to constrain the substitution to s/^;.*//; at least? Commented Dec 21, 2024 at 2:56
2

A simple awk one-liner awk '/^;/{next}1' input_file should do the trick.

[jaypal:~/Temp] cat file ; - Show all errors, except for notices ; ;error_reporting = E_ALL & ~E_NOTICE ; ; - Show only errors ; ;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR ; ; - Show all errors except for notices ; error_reporting = E_ALL & ~E_NOTICE [jaypal:~/Temp] awk '/^;/{next}1' file error_reporting = E_ALL & ~E_NOTICE [jaypal:~/Temp] 
1
  • 5
    Correct, but verbose. Just awk '!/^;/' input_file is enough. Commented Dec 8, 2011 at 9:32
2

As well as Jaypal, I also most probably would use awk for these purposes. It worse to mention that perl is sometimes quite handy for such purposes:

cat data.txt | perl -lne "print unless /^;/" 

Perl regexps are more powerful compared to awk's one and sometimes you might need them.

3
  • 1
    +1 for perl, although the cat and the -l are both redundant, so a simpler invocation is perl -ne 'print unless /^;/' data.txt Commented Dec 8, 2011 at 3:59
  • @Simone Whitaker, yes, you are right - it is just a habit to write it the way i write, and it worth to mention it. Commented Dec 8, 2011 at 4:18
  • 1
    Sure thing. In fact, I think cat works fine in these examples if you consider it as a proxy for the more generic "anything generating text on STDOUT". Unix pipes are the best thing since sliced bread, imho. :) Commented Dec 8, 2011 at 9:43
1

Here's one that I use, just substitute ';' with the comment character (e.g. '#' for many UNIX service configuration files):

grep -Ev '^[[:space:]]*;|^$' chan_dahdi.conf.sample | sed 's/;.*$//' 

That gets rid of all whole-line comments (even if they have leading whitespace), and any comments that end non-comment lines, and succinctly removes blank lines from the output as well. This may be possible without the pipeline (my sed- or awk-fu is admittedly not great), but it's so easy for me to understand (and remember), I figured I'd post it here.

1

Example show only lines + do not show new lines or emtpy lines:

$ egrep -v '^(;|#|//)' /etc/ssh/sshd_config | tr '\n' ' ' Protocol 2 SyslogFacility AUTHPRIV PasswordAuthentication yes ChallengeResponseAuthentication no GSSAPIAuthentication yes GSSAPICleanupCredentials yes UsePAM yes AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS X11Forwarding yes Subsystem sftp /usr/libexec/openssh/sftp-server 

OR

$ egrep -v '^(;|#|//|$)' /etc/ssh/sshd_config Protocol 2 SyslogFacility AUTHPRIV PasswordAuthentication yes ChallengeResponseAuthentication no GSSAPIAuthentication yes GSSAPICleanupCredentials yes UsePAM yes AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS X11Forwarding yes Subsystem sftp /usr/libexec/openssh/sftp-server 
1
  • 2
    The use of egrep is long deprecated. grep -E is the command you're looking for here. Commented Mar 13, 2014 at 16:23
0

you can use the following command to save the lines, excluding empty lines and lines starting with # in a new file

cat <file to be read> | egrep -v '^#|^$' > <file to be written at>

1
  • Useless cat pipe and egrep is depreciated and to be replaced with grep -E for extended expressions or just grep -v. Commented Jan 11, 2018 at 8:19
-2
cat /etc/ssh/sshd_config | grep "^\b" 

This one works pretty good.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.