35
votes

I'd like to print out a file containing a series of comments like:

    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn
    CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
    #   SSL Engine Switch:

In essence, the file contains multiple indentation levels, where a comment starts with a # symbol.

grep should remove blank lines, and also lines where there is a hash symbol before text (implying that these are comments).

I know that blank lines can be deleted via: grep -v '^$'

However how can I delete lines with leading whitespace, and then a # symbol, and print out only lines with actual code? I would like to do this in bash, using grep and/or sed.

18

18 Answers

76
votes

With grep:

grep -v '^\s*$\|^\s*\#' temp

On OSX / BSD systems:

grep -Ev '^\s*$|^\s*\#' temp
28
votes

With awk:

awk '!/^ *#/ && NF' file
  • !/^ *#/ - means select lines which do not have space followed by # symbol
  • NF - means select lines which are not blank
  • && - is an and operator which ensure if both of the above are true then print the line.
8
votes

This is probably easier with sed than grep:

sed -e '/^[[:space:]]*$/d' -e '/^[[:space:]]*#/d' test.in

Or with an ERE:

# Gnu sed need -re instead of -Ee
sed -Ee '/^[[:space:]]*(#|$)/d' test.in

With the ERE, grep can do it fairly easily too:

# Not sure if Gnu grep needs -E or -r
grep -vE '^\s*(#|$)' test.in

# or a BRE
grep -v '^\s*\(#\|$\)' test.in
5
votes

Code for GNU :

sed -r '/^(\s*#|$)/d;' file

$cat file
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    next line is empty

       line with leading space
       # line with leading space and #
    LogLevel warn
        #line with leading tab and #
        line with leading tab
    CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
    #   SSL Engine Switch:
$sed -r '/^(\s*#|$)/d;' file
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    next line is empty
       line with leading space
    LogLevel warn
        line with leading tab
    CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
4
votes

Little Upgrade

grep -v '^\s*$\|^#\|^\s*\#' filename

This code excludes empty lines or lines with only spaces, lines beginning with #, and lines containing nothing but spaces before #.

PS: ^# is different than ^\s*#

3
votes

This one should do:

sed 's/[[:space:]]*#.*//;/^[[:space:]]*$/d' file

On this input:

Hello everybody

# This is a comment and the previous line was empty

This is a genuine line followed by a comment # this is the comment


              # and here a comment in the middle of nowhere

you'll obtain this output:

Hello everybody
This is a genuine line followed by a comment

Caveat. This kind of method is not 100% foolproof: if you have a pound sign (#) not starting a comment, i.e., it's escaped or inside a string, well, you can imagine what will happen.

3
votes
grep ^[^#] filename
  • ^ - begin of line

  • [^#]- exclude #.

If you have spaces in the begin of line it won't work.

1
votes

egrep -v '^$|^#' /etc/sysctl.conf

1
votes
sed -n '/^\s*[^#]\|^$/!'p filename

Pattern will match any amount of whitespaces (or zero) starting at the beginning of the line and following by any character that is not a #
OR empty string (nothing at all in between ^ and $).
To NOT match it, sed allows the usage of ! operator (invert match). Now pattern matches anything that regular expression don't fits in.
Thus with combination of -n (suppress of printing anything) and p flag (print) lines matching anything except the pattern will be printed.

1
votes

Using default space separator

  • empty line or line with blank only have an empty $1
  • line with first non blank¨char is #, have $1 starting with #

so, keep it simple

awk '$1 ~ /^[^#]/ ' YourFile
1
votes

Can't think of anything simpler than:

grep -v '^ *#\|^$' filename

You can test with this file:

# comment
 # comment with space before
  # comment with two spaces before
line with text and # comment at the end

line with text

(edited to include a ' *' and handle comments with leading spaces)

0
votes
grep -v '^$\|^#\|^\s*\#' filename

Excludes empty lines, lines beginning with # and lines containing nothing but spaces before #.

0
votes
#!/bin/bash


#---------------------------------------------------------------#
#             Programacion Shell                                #
#             ------------------                                #
#  Programa:  xable.sh  (eXecutABLEs)                           #
###                                                           ###
#  OBJETIVO:  Filtrar solo las lineas ejecutables de un shell   #
#                                    (eXecutABLEs)              #
###                                                           ###
#  Autor...:  Francisco Eugenio Cabrera Perez                   #
#  Pais....:  Republica Dominicana                              #
#  Fecha...:  Abril 6 del 2015                                  #
#---------------------------------------------------------------#

         x_FILE=$1
if [ -z $x_FILE ];then
   echo
   echo "      $0 :  Sin Argumento^G"; echo
   echo "USO:  $0 ARCHIVO";            echo
###
   exit 1
fi
#####


#  Ignore COMMENTs and lines that...
#  ---------------------------------
#      EXPLANATION                            (PATTERN)         OBSERVATION
#      -----------                            ---------         -----------
#  1.  Begin_and_End_with_NOTHING             (^$)              NO_Characters
###
#  2.  Begin_with_HASH_symbol                 (^#)              COMMENT
#  3.  Begin_with_SPACE_and_then_HASH_symbol  (^\s*\#)          COMMENT
###
#  4.  Begin_and_End_with_SPACES              (^[[:space:]]*$)  Only_SPACES
#  -------------------------------------------------------------------------
#####
    grep -v '^$\|^#\|^\s*\#' $x_FILE | grep -v "^[[:space:]]*$" | more
#####
0
votes
grep -v '^$\|^#\|^\s*\#' filename | grep -v "^[[:space:]]*$" | more
0
votes

With Perl:

perl -lne 'print if ! /^\s*(#.*)?$/' file

This will also ignore C++ comments (//)

perl -lne 'print if ! m{^\s*((#|//).*)?$}' file
0
votes

The following:

grep -v '^#\|^$\|^\s+$' file

Would hide lines beginning with #, empty lines and lines that only contain white spaces from be printed out to the stdout. Notice that the | character has to be escaped. Hope that helps

0
votes

Here's a simple one-liner grep. This will get rid of hashes and empty lines.

grep -ve '^#' -ve '^$' /path/to/the/file

have fun.

-1
votes
cat filename| egrep -v "^\s*$|^;|^\s*#
  • First, cat the file
  • egrep -v removes
  • ^$ starting with empty line
  • ^; starting with ;
  • ^\s matches any leading whitespace, then any character until #