1

I read through the manpage of Sed, but I still find it quite confusing, so I hope to find some answers here :)

I need to edit a file using a bash script.

I need to place a couple of lines after a specific line inside grub.cfg. For the purpose of showing an example, I will add 5 newly added lines.

Original:

if loadfont /boot/grub/font.pf2 ; then
    set gfxmode=auto
    insmod efi_gop
    insmod efi_uga
    insmod gfxterm
    terminal_output gfxterm
fi

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray

menuentry "Install Ubuntu Server" {
    set gfxpayload=keep
    linux   /install/vmlinuz  file=/cdrom/preseed/ubuntu-server.seed quiet ---
    initrd  /install/initrd.gz
}
menuentry "OEM install (for manufacturers)" {
    set gfxpayload=keep
    linux   /install/vmlinuz  file=/cdrom/preseed/ubuntu-server.seed quiet oem-config/enable=true ---
    initrd  /install/initrd.gz
}

After edit:

if loadfont /boot/grub/font.pf2 ; then
    set gfxmode=auto
    insmod efi_gop
    insmod efi_uga
    insmod gfxterm
    terminal_output gfxterm
fi

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
newly_addedd_line_1
newly_addedd_line_2
newly_addedd_line_3
newly_addedd_line_4
newly_addedd_line_5

menuentry "Install Ubuntu Server" {
    set gfxpayload=keep
    linux   /install/vmlinuz  file=/cdrom/preseed/ubuntu-server.seed quiet ---
    initrd  /install/initrd.gz
}
menuentry "OEM install (for manufacturers)" {
    set gfxpayload=keep
    linux   /install/vmlinuz  file=/cdrom/preseed/ubuntu-server.seed quiet oem-config/enable=true ---
    initrd  /install/initrd.gz
}

How would that work using sed? Ideally I would have all the new lines inside a new script variable.

For example:

LINES_TO_ADD='newly_addedd_line_1\n
newly_addedd_line_2\n
newly_addedd_line_3\n
newly_addedd_line_4\n
newly_addedd_line_5'

Thank you in advance!

1
  • you can echo the variable value and use r command with /dev/stdin as filename...
    – Sundeep
    Commented Jul 11, 2017 at 15:54

3 Answers 3

1
sed '/^set menu_color_highlight/a\
newly_addedd_line_2\
newly_addedd_line_3\
newly_addedd_line_4\
newly_addedd_line_5' /path/to/file

Once you have verified the output, you can use sed --in-place or write to a new file and swap the old version out.

From the manual:

 [1addr]a\
 text    Write text to standard output immediately before each attempt to read
         a line of input, whether by executing the ``N'' function or by beginning
         a new cycle.

Possibly slightly more robustly, you can put your new block of text into a file (e. g. newlines), and then use:

sed '^set menu_color_highlight/r newlines' /path/to/input.

Again, from the manual:

 [1addr]r file
         Copy the contents of file to the standard output immediately before the
         next attempt to read a line of input.  If file cannot be read for any
         reason, it is silently ignored and no error condition is set.
1
  • have to be careful with escape sequences using this method... for ex \n will get converted to newline... using r command is robust and can easily use multiline value from shell variable as well
    – Sundeep
    Commented Jul 11, 2017 at 15:56
0
LINES_TO_ADD='newly_addedd_line_1
newly_addedd_line_2
newly_addedd_line_3
newly_addedd_line_4
newly_addedd_line_5'
LINES_TO_ADD_ESC=$(printf '%s\n' "$LINES_TO_ADD" | sed 's:[\/&]:\\&:g;$!s/$/\\/')
sed -e "
        /^set menu_color_highlight=/G
        //s/\$/$LINES_TO_ADD_ESC/
"
0

If the specific line number never changes, then you can use something like:

sed -i '11inewly_addedd_line_1 \
newly_addedd_line_2 \
newly_addedd_line_3 \
newly_addedd_line_4 \
newly_addedd_line_5' /path/to/your/grub.cfg

and you can double check that it'll do what you want first by just not including the '-i' flag (without it, this will print out the file with your changes, but won't actually change the file).

If you want to add it after a pattern match and the pattern you're putting in contains the whole line, then you can do this:

sed -i '/set menu_color_highlight=black\/light-gray/a \
newly_addedd_line_1 \
newly_addedd_line_2 \
newly_addedd_line_3 \
newly_addedd_line_4 \
newly_addedd_line_5' /path/to/your/grub.cfg

Where /PATTERN/a means to append after the pattern.

You can also add things before a line usine /PATTERN/i to insert.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .