sed 将文本放置在特定行之后

sed 将文本放置在特定行之后

我通读了 Sed 的联机帮助页,但仍然觉得它很混乱,所以我希望在这里找到一些答案:)

我需要使用 bash 脚本编辑文件。

我需要在 grub.cfg 中的特定行之后放置几行。为了展示示例,我将新添加 5 行。

原来的:

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
}

编辑后:

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
}

使用 sed 会如何工作?理想情况下,我会将所有新行放在新的脚本变量中。

例如:

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'

先感谢您!

答案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

验证输出后,您可以使用sed --in-place或写入新文件并交换旧版本。

从手册:

 [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.

可能稍微更稳健一些,您可以将新的文本块放入文件中(例如newlines),然后使用:

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

再次,来自手册:

 [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.

答案2

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/
"

答案3

如果特定的行号永远不会改变,那么您可以使用类似以下内容的内容:

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

您可以通过不包含“-i”标志来仔细检查它是否会首先执行您想要的操作(如果没有它,这将打印出包含您的更改的文件,但实际上不会更改该文件)。

如果您想在模式匹配之后添加它并且您要放入的模式包含整行,那么您可以这样做:

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

其中 /PATTERN/a 表示追加到模式之后。

您还可以在使用 /PATTERN/i 插入的行之前添加内容。

相关内容