drewrockshard
drewrockshard

Reputation: 2071

Ignore comments (#) using sed, but keep the lines untouched

I have a config file that I want to basically edit the uncommented lines, but not the commented lines. I'm using sed.

For example, I have a file called file.txt:

test
# test
# test
test

I want to replace "test" with "TEST" but do NOT touch the commented lines. Final output should show:

TEST
# test
# test
TEST

Upvotes: 17

Views: 18601

Answers (5)

user42723
user42723

Reputation: 621

To ignore comments that start with a # when doing a substitution, you can use the following command:

sed -r 'h;s/[^#]*//1;x;s/#.*//;(substitution command);G;s/(.*)\n/\1/' file.txt

In your case it becomes:

sed -r 'h;s/[^#]*//1;x;s/#.*//;s/test/TEST/g;G;s/(.*)\n/\1/' file.txt

The advantage of this solution over the other solutions is that it will also work if there is a comment starting later in a line, as shown in the example below. Since this solution uses the hold buffer of sed, this solution is not possible if you need to use the hold buffer for something else.

Input

test
# test
test # test
test

Output

TEST
# test
TEST # test
TEST

Explanation

  1. h; - Save in hold buffer
  2. s/[^#]*//1; - Remove everything before #
  3. x; - Swap with hold buffer
  4. s/#.*//; - Remove the comment
  5. s/test/TEST/g; - Replace all occurences of test with TEST
  6. G; - Append newline + hold buffer (the comment)
  7. s/(.*)\n/\1/ - Remove the last newline

The -r switch is required for using \1.

Upvotes: 3

kurumi
kurumi

Reputation: 25609

if you have Ruby(1.9+)

ruby -ne 'print $_ !~ /^\s*#/ ?gsub("test","TEST"):$_' file

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 247220

awk:

awk '!/^[[:space:]]*#/ {gsub(/test/,"TEST")} 1' file.txt

Upvotes: 1

dty
dty

Reputation: 18998

I'm not a sed expert, but the regexp to match those lines will look something like this:

^[^#].*test

  • ^ - beginning of line
  • [^#] - first character, anything except #
  • .* - some more characters, undefined
  • test - the string you're looking for

Upvotes: 3

SiegeX
SiegeX

Reputation: 140557

sed '/^#/!s/test/TEST/g' /path/to/infile

Output

$ sed '/^#/!s/test/TEST/g' infile
TEST
# test
# test
TEST

*Note: If your only requirement for a comment is that the very first non-whitespace character is a #, then you can use:

sed '/^[[:space:]]*#/!s/test/TEST/g' /path/to/infile

Output

$ sed '/^[[:space:]]*#/!s/test/TEST/g' infile
TEST
# test
 # test
TEST

Upvotes: 30

Related Questions