1

I have the following script:

#!/bin/bash

LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1"
NEW_LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1 elevator=deadline"

#sed -i "/${LINE}/c ${NEW_LINE}" grub.cfg

LINE1="insmod lvm"
NEW_LINE1="insmod lvm x"

sed -i "/${LINE1}/c ${NEW_LINE1}" grub.cfg

Can someone tell me why the commented sed does not work (Error: sed: -e expression #1, char 10: extra characters after command), but the uncommented one does, when only the strings are different?

0

2 Answers 2

1

Since there are slashes in the line that you're looking for, you need to use a different character to mark the boundaries of the s/// command. For example, you don't have any % symbols in the strings, so:

LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1"
NEW_LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1 elevator=deadline"

sed -i "s%.*${LINE}.*%${NEW_LINE}%" grub.cfg

Or, keeping the change command, you need to use a different character in the match — you use a backslash in front of it to indicate that's what you're doing.

LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1"
NEW_LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1 elevator=deadline"

sed -i "\%${LINE}%c ${NEW_LINE}" grub.cfg

The POSIX specification for sed says:

The sed utility shall support the BREs described in XBD Basic Regular Expressions, with the following additions:

  • In a context address, the construction "\cBREc", where c is any character other than <backslash> or <newline>, shall be identical to "/BRE/". If the character designated by c appears following a <backslash>, then it shall be considered to be that literal character, which shall not terminate the BRE. For example, in the context address "\xabc\xdefx", the second x stands for itself, so that the BRE is "abcxdef".

and:

[2addr]s/BRE/replacement/flags
Substitute the replacement string for instances of the BRE in the pattern space. Any character other than <backslash> or <newline> can be used instead of a <slash> to delimit the BRE and the replacement. Within the BRE and the replacement, the BRE delimiter itself can be used as a literal character if it is preceded by a <backslash>.

Sign up to request clarification or add additional context in comments.

2 Comments

Note, too, that the c command with the data on the same line is a GNU sed extension, and the -i option with no suffix is likewise a GNU sed extension. BSD sed (on macOS, for example) supports -i but requires an extension; to indicate a null extension for the backup, use -i '' (note that the empty argument must be separate). The portable backup notation is -i.bak with no space between the -i and the suffix; that works with both GNU and BSD variants.
Hi Jonathan, thank you for your help. It works for me.
0

The uncommented line does not work because the delimiter your sed expression uses appears in the thing you are matching and replacing.

LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1"
NEW_LINE="linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1 elevator=deadline"

sed -i "/${LINE}/c ${NEW_LINE}" grub.cfg

Your sed expression will resolve to:

/linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1/c linux /disk0/vmlinuz rw root=/dev/mapper/VolGroup1-disk0_root console=tty0 clock=pit aacraid.msi=1 elevator=deadline

As you can see, this results in more operations in the expression than sed expects, hence your error message extra characters after command.

If you change your delimiter to a different character it should work:

sed -i "\:${LINE}:c ${NEW_LINE}" grub.cfg

You could also use the s command — try:

sed -i "s:${LINE}:c ${NEW_LINE}:g" grub.cfg

2 Comments

Hi ConMan, thank you for your reply. The reason why it is not working is correct, but seems my version of sed is not new enough for the proposed solution. But thank you for your replay anyway. It helped me a lot.
@maimun4itu: Which version of sed are you using (sed --version)? This isn't something that's changed recently (in the last 10 years or more), so it'll be surprising if it is the version that's the trouble. There is more likely to be trouble with your transcription of the proposed solutions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.