Quratul Ain Shafiq
Quratul Ain Shafiq

Reputation: 119

sed comand is not replacing value after first match

I am trying to add a line in a file using sed after first match. I looked my threads online, addressing the same issue and tried below versions of the command:

  1. sudo sed -e '/cfg_file/cfg_file='$NEW_FILE -e '/cfg_file/cfg_file=/q' MAIN_CONF_FILE
  2. sudo sed -i '0,/cfg_file/ a\cfg_file='$NEW_FILE $MAIN_CONF_FILE
  3. sudo sed -i '1s/cfg_file/cfg_file='$NEW_FILE $MAIN_CONF_FILE
  4. sudo sed -i '1/cfg_file/s/cfg_file='$NEW_FILE $MAIN_CONF_FILE

Unfortunately, nothing worked for me. Either they show error, in case of point 3, or show similar behavior of adding lines after each match.

SAMPLE FILE

cfg_file=some_line1
cfg_file=some_line2

Now I want to add a line after first match of cg_file, like below.

EXPECTED RESULT

cfg_file=some_line1
cfg_file=my_added_line_after_first_match_only.
cfg_file=some_line2

Help me in adding line after first match and correcting my command.

Upvotes: 1

Views: 54

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753525

Since you're on Ubuntu, you are using GNU sed. GNU sed has some weird features and some useful ones; you should ignore the weird ones and use the useful ones.

In context, the useful one is ranges starting at line 0. Weird ones are the way it messes with a, i and c commands.

MAIN_CONF_FILE=/tmp/copy.of.main.config.file
NEWFILE="my_added_line_after_first_match_only."

sed -e '0,/^cfg_file=/ { /^cfg_file/ a\' \
    -e "cfg_file=$NEWFILE" \
    -e '}' \
    "$MAIN_CONF_FILE"

In classic sed, the a command is followed by backslash-newline, and each subsequent line of the script is appended up to and including the first line without a backslash at the end (and the backslash is removed). Each -e argument functions as a line in the script. Distinguish between the shell lines escaped with backslash at the end and the sed script lines with backslash at the end.

Example at work

$ cat /tmp/copy.of.main.config.file | so
cfg_file=some_line1
cfg_file=some_line2
$ cat script.sh
MAIN_CONF_FILE=/tmp/copy.of.main.config.file
NEWFILE="my_added_line_after_first_match_only."

SED=/opt/gnu/bin/sed

${SED} \
    -e '0,/^cfg_file=/ { /^cfg_file/ a\' \
    -e "cfg_file=$NEWFILE" \
    -e '}' \
    "$MAIN_CONF_FILE"
$ bash script.sh
cfg_file=some_line1
cfg_file=my_added_line_after_first_match_only.
cfg_file=some_line2
$

This is based on your attempt 2, but avoids some of the weird stuff.

Basic sanity

As I noted, it is not sensible to experiment with sudo and the -i option to sed. You don't use those until you know that the script will do the job correctly. It is dangerous to do anything as root via sudo. It is doubly dangerous when you don't know whether what you're trying to use will work. Don't risk wrecking your system.

Upvotes: 2

Related Questions