Bash脚本:替换文件中的一行

时间:2017-03-29 14:58:53

标签: bash sed

我有以下脚本:

#!/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

有人可以告诉我为什么评论的sed不起作用(错误:sed: -e expression #1, char 10: extra characters after command),但是当只有字符串不同时,未注释的sed会这样做吗?

2 个答案:

答案 0 :(得分:1)

由于您要查找的行中有斜杠,因此您需要使用不同的字符来标记s///命令的边界。例如,字符串中没有任何%符号,因此:

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

或者,保持更改命令,您需要在匹配中使用不同的字符 - 在它前面使用反斜杠来表示您正在做的事情。

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

sed的POSIX规范说:

  

sed实用程序应支持XBD Basic正则表达式中描述的BRE,并添加以下内容:

     
      
  • 在上下文地址中,构造“\cBREc”,其中c<backslash><newline>以外的任何字符,应与“{{1}相同}”。如果/BRE/指定的字符出现在c之后,则应将其视为该字面字符,该字符不应终止BRE。例如,在上下文地址“<backslash>”中,第二个\xabc\xdefx代表自己,因此BRE为“x”。
  •   

  

abcxdef
      将替换字符串替换为模式空间中BRE的实例。可以使用[2addr]s/BRE/replacement/flags<backslash>以外的任何字符代替<newline>来分隔BRE和替换字符。在BRE和替换中,如果BRE分隔符前面有<slash>,则它可以用作文字字符。

答案 1 :(得分:0)

未注释的行无法使用,因为sed表达式使用的分隔符出现在您要匹配和替换的内容中。

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

您的sed表达式将解析为:

/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

如您所见,这导致表达式中的操作比sed预期的更多,因此您的错误消息为extra characters after command

如果您将分隔符更改为其他字符,则应该有效:

sed -i "\:${LINE}:c ${NEW_LINE}" grub.cfg

您也可以使用s命令 - 尝试:

sed -i "s:${LINE}:c ${NEW_LINE}:g" grub.cfg