Bash脚本:替换文件中的一行
我有以下脚本:Bash脚本:替换文件中的一行,bash,sed,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=deadl
#!/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:command之后的额外字符
),但未注释的sed起作用,只有字符串不同时?未注释的行不起作用,因为您要匹配和替换的内容中出现了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预期的要多,因此错误消息命令后会出现额外字符
如果将分隔符更改为其他字符,则应该可以:
sed -i "\:${LINE}:c ${NEW_LINE}" grub.cfg
您也可以使用s
命令-尝试:
sed -i "s:${LINE}:c ${NEW_LINE}:g" grub.cfg
由于要查找的行中有斜杠,因此需要使用不同的字符来标记
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
或者,保留change命令,您需要在匹配中使用不同的字符-在其前面使用反斜杠来指示您正在执行的操作
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
的POSIX规范说明:
sed实用程序应支持XBD基本正则表达式中描述的BRE,并添加以下内容:
- 在上下文地址中,结构“
”,其中\cBREc
是c
或
以外的任何字符,应与“
”相同。如果/BRE/
指定的字符出现在c
之后,则应将其视为该文字字符,该文字字符不得终止BRE。例如,在上下文地址“
”中,第二个\xabc\xdefx
代表它自己,因此BRE是“x
”abcxdef
[2addr]s/BRE/replacement/flags
用替换字符串替换模式空间中BRE的实例。可以使用
或
以外的任何字符代替
来分隔BRE和替换。在BRE和替换中,如果BRE分隔符前面有
,则可以将其本身用作文字字符
还要注意的是,数据在同一行的
c
命令是GNUsed
扩展,没有后缀的-i
选项也是GNUsed
扩展。BSDsed
(例如,在macOS上)支持-i
,但需要扩展;要指示备份的空扩展名,请使用-i'
(请注意,空参数必须分开)。便携式备份符号为-i.bak
,在-i
和后缀之间没有空格;这适用于GNU和BSD变体。嗨,乔纳森,谢谢你的帮助。这对我有用。嗨,康曼,谢谢你的回复。它不起作用的原因是正确的,但我的sed版本对于建议的解决方案来说似乎不够新。不过还是谢谢你的重播。这对我帮助很大。@maimun4itu:您使用的是哪个版本的sed
(sed--version
)?这并不是最近(在过去10年或更长的时间里)发生的变化,所以如果问题出在这个版本上,那将是令人惊讶的。您对建议的解决方案的转录更可能出现问题。