Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash脚本:替换文件中的一行_Bash_Sed - Fatal编程技术网

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
    ”中,第二个
    x
    代表它自己,因此BRE是“
    abcxdef
以及:

[2addr]s/BRE/replacement/flags

用替换字符串替换模式空间中BRE的实例。可以使用
以外的任何字符代替
来分隔BRE和替换。在BRE和替换中,如果BRE分隔符前面有
,则可以将其本身用作文字字符


还要注意的是,数据在同一行的
c
命令是GNU
sed
扩展,没有后缀的
-i
选项也是GNU
sed
扩展。BSD
sed
(例如,在macOS上)支持
-i
,但需要扩展;要指示备份的空扩展名,请使用
-i'
(请注意,空参数必须分开)。便携式备份符号为
-i.bak
,在
-i
和后缀之间没有空格;这适用于GNU和BSD变体。嗨,乔纳森,谢谢你的帮助。这对我有用。嗨,康曼,谢谢你的回复。它不起作用的原因是正确的,但我的sed版本对于建议的解决方案来说似乎不够新。不过还是谢谢你的重播。这对我帮助很大。@maimun4itu:您使用的是哪个版本的
sed
sed--version
)?这并不是最近(在过去10年或更长的时间里)发生的变化,所以如果问题出在这个版本上,那将是令人惊讶的。您对建议的解决方案的转录更可能出现问题。