Reputation: 45
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?
Upvotes: 1
Views: 103
Reputation: 1652
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
Upvotes: 0
Reputation: 755064
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
", wherec
is any character other than<backslash>
or<newline>
, shall be identical to "/BRE/
". If the character designated byc
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 secondx
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>
.
Upvotes: 1