0

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!

  • you can echo the variable value and use r command with /dev/stdin as filename... – Sundeep Jul 11 '17 at 15:54
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.
  • 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 Jul 11 '17 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.