匹配来自文件的第一个文本块,在2个string之间

我试图匹配2个string之间的第一个文本块:“menuentry”和“}”,如下所示:

input文件:

(some irrelevant text) menuentry 'My Customized Linux, with Linux 3.10.0-229.14.1.el7.x86_64' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-229.14.1.el7.x86_64-advanced-/dev/mapper/sysvg-lv_root' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 2e420275-8578-449d-9217-ce6d9ae35f70 else search --no-floppy --fs-uuid --set=root 2e420275-8578-449d-9217-ce6d9ae35f70 fi linux16 /vmlinuz-3.10.0-229.14.1.el7.x86_64 root=/dev/mapper/sysvg-lv_root ro nomodeset rd.lvm.lv=sysvg/lv_swap vconsole.keymap=us rd.lvm.lv=sysvg/lv_root vconsole.font=latarcyrheb-sun16 rootfstype=xfs crashkernel=auto quiet LANG=en_US.UTF-8 initrd16 /initramfs-3.10.0-229.14.1.el7.x86_64.img } menuentry 'My Customized Linux (Rescue)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-2e4c8e37e48347b0b4fa7095fbd707db-advanced-/dev/mapper/sysvg-lv_root' { load_video insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 2e420275-8578-449d-9217-ce6d9ae35f70 else search --no-floppy --fs-uuid --set=root 2e420275-8578-449d-9217-ce6d9ae35f70 fi linux16 /vmlinuz-0-rescue-2e4c8e37e48347b0b4fa7095fbd707db root=/dev/mapper/sysvg-lv_root ro nomodeset rd.lvm.lv=sysvg/lv_swap vconsole.keymap=us rd.lvm.lv=sysvg/lv_root vconsole.font=latarcyrheb-sun16 rootfstype=xfs crashkernel=auto quiet initrd16 /initramfs-0-rescue-2e4c8e37e48347b0b4fa7095fbd707db.img } (some more irrelevant text) 

输出应该是:

 menuentry 'My Customized Linux, with Linux 3.10.0-229.14.1.el7.x86_64' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-229.14.1.el7.x86_64-advanced-/dev/mapper/sysvg-lv_root' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 2e420275-8578-449d-9217-ce6d9ae35f70 else search --no-floppy --fs-uuid --set=root 2e420275-8578-449d-9217-ce6d9ae35f70 fi linux16 /vmlinuz-3.10.0-229.14.1.el7.x86_64 root=/dev/mapper/sysvg-lv_root ro nomodeset rd.lvm.lv=sysvg/lv_swap vconsole.keymap=us rd.lvm.lv=sysvg/lv_root vconsole.font=latarcyrheb-sun16 rootfstype=xfs crashkernel=auto quiet LANG=en_US.UTF-8 initrd16 /initramfs-3.10.0-229.14.1.el7.x86_64.img } 

我用这个sed如下:

sed -n'/ ^ menuentry /,/ ^} $ / p;' /boot/grub2/grub.cfg

但总是得到第一个“menuentry”和最后一个“}”之间的整个文本

  [root@ball ~]# sed -n '/^menuentry /,/^}$/p;' /boot/grub2/grub.cfg menuentry 'My Customized Linux, with Linux 3.10.0-229.14.1.el7.x86_64' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-229.14.1.el7.x86_64-advanced-/dev/mapper/sysvg-lv_root' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 2e420275-8578-449d-9217-ce6d9ae35f70 else search --no-floppy --fs-uuid --set=root 2e420275-8578-449d-9217-ce6d9ae35f70 fi linux16 /vmlinuz-3.10.0-229.14.1.el7.x86_64 root=/dev/mapper/sysvg-lv_root ro nomodeset rd.lvm.lv=sysvg/lv_swap vconsole.keymap=us rd.lvm.lv=sysvg/lv_root vconsole.font=latarcyrheb-sun16 rootfstype=xfs crashkernel=auto quiet LANG=en_US.UTF-8 initrd16 /initramfs-3.10.0-229.14.1.el7.x86_64.img } menuentry 'My Customized Linux (Rescue)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-2e4c8e37e48347b0b4fa7095fbd707db-advanced-/dev/mapper/sysvg-lv_root' { load_video insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 2e420275-8578-449d-9217-ce6d9ae35f70 else search --no-floppy --fs-uuid --set=root 2e420275-8578-449d-9217-ce6d9ae35f70 fi linux16 /vmlinuz-0-rescue-2e4c8e37e48347b0b4fa7095fbd707db root=/dev/mapper/sysvg-lv_root ro nomodeset rd.lvm.lv=sysvg/lv_swap vconsole.keymap=us rd.lvm.lv=sysvg/lv_root vconsole.font=latarcyrheb-sun16 rootfstype=xfs crashkernel=auto quiet initrd16 /initramfs-0-rescue-2e4c8e37e48347b0b4fa7095fbd707db.img } 

有任何想法吗?

一行sed

 sed -n '/^menuentry/,/\}$/{p;/^\}$/q}' 

/^\}$/q表示“如果行匹配模式/^\}$/然后退出”

这对我使用多次通行证

 sed -n '/^menuentry /,$p' /boot/grub2/grub.cfg | tr '\n' '~' | sed 's/~menuentry.*//' | tr '~' '\n' 

说明

  • sed -n '/^menuentry /,$p' /boot/grub2/grub.cfg – 删除文件头到第一个menuentry
  • tr '\n' '~' – 将输出转换为一行
  • sed 's/~menuentry.*//' – 使用sed从\nmenuentry (现在~menuentry )中删除到string的末尾
  • tr'〜 tr '~' '\n' – 将string恢复为多个输出

如果Perl会做…

  perl -lne '$p=1 if(/^menuentry/);print if $p;exit if (/^}$/)' /boot/grub2/grub.cfg 

 menuentry 'My Customized Linux, with Linux 3.10.0-229.14.1.el7.x86_64' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-229.14.1.el7.x86_64-advanced-/dev/mapper/sysvg-lv_root' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 2e420275-8578-449d-9217-ce6d9ae35f70 else search --no-floppy --fs-uuid --set=root 2e420275-8578-449d-9217-ce6d9ae35f70 fi linux16 /vmlinuz-3.10.0-229.14.1.el7.x86_64 root=/dev/mapper/sysvg-lv_root ro nomodeset rd.lvm.lv=sysvg/lv_swap vconsole.keymap=us rd.lvm.lv=sysvg/lv_root vconsole.font=latarcyrheb-sun16 rootfstype=xfs crashkernel=auto quiet LANG=en_US.UTF-8 initrd16 /initramfs-3.10.0-229.14.1.el7.x86_64.img } 

或这个:

 perl -lne 'BEGIN{$/="\nmenuentry "};if($.==2){print $/,$_;last}' /boot/grub2/grub.cfg 

(这个版本设置perl行分割以menuentry行的开始结束,然后打印实际上是你想要的那个“第二个”节。