我正在寻找有关如何搜索文件中字符串的一部分并替换完整行或将该字符串附加到该文件(如果找不到)的建议。我现在用 sed “玩”了一段时间,但无法让它按预期工作。
我需要补充:
/swapfile none swap sw 0 0
到/etc/fstab
(在Ubuntu 14.04 - 值得信赖的塔尔)。
状况:
- 如果
/swapfile
中存在以 开头的任何行/etc/fstab
,请删除该行并替换为上面提供的字符串 - 如果找到多于一行以开头的行
/swapfile
,请将其全部删除并将上面的字符串附加到文件末尾 - 如果
/swapfile
中不存在/etc/fstab
,则将字符串附加到/etc/fstab
- 该命令不得显示控制台输出,并且必须是“一行”(由于木偶的自动化目的)
我相信这是可能的,但我只是没有找到有关以我需要的方式使用 sed 的相关教程。
我用过sudo sed -i '$a/swapfile none swap sw 0 0' /etc/fstab
,但这只附加了字符串:(
答案1
您可以使用 sed 来完成此操作 - 它是图灵完备的。但它并不是完成这项工作的最佳工具。 Sed 没有一种方便的方法来记住它已经进行了替换。
使用 sed 可以相对轻松地执行的操作是清空所有以 开头的行/swapfile
,并在末尾添加一个新行:
sed -i '$! s/^\/swapfile[\t ]//; $s/\(^\/swapfile.*\)\?$/\n\/swapfile none swap sw/' /etc/fstab
但除此之外,我们很快就进入了一个领域,我不会将这样的 sed 代码留给另一个系统管理员来维护,特别是当简单、可读的 shell 命令组合会做得更好时:
{ </etc/fstab grep -v '/swapfile[\t ]'; echo '/swapfile none swap sw'; } >/etc/fstab.new && mv /etc/fstab.new /etc/fstab
如果您想保留该/swapfile
行的现有位置(如果存在)并且仅在需要修改时才修改该文件,那么 shell 逻辑和 awk 的组合是更好的工具。为了清楚起见,我在这里使用了多行,但如果您愿意,您可以将所有代码放在同一行上。作为奖励,如果文件已经包含预期的行(具有精确的间距),则不会对其进行修改。
awk '
/\/swapfile[\t ]/ {if (replaced) {next}
else {replaced=1; print "/swapfile none swap sw"}}
1 {print}
END {if (!replaced) print "/swapfile none swap sw"}
' /etc/fstab >/etc/fstab.new &&
if cmp -s /etc/fstab.new /etc/fstab.new; then
rm /etc/fstab.new;
else
mv /etc/fstab.new /etc/fstab;
fi
答案2
由于您使用 Puppet 来自动执行此操作,因此最好让 Puppetfstab
为您处理。使用挂载资源类型。
就像是:
mount{'swapfile':
name => 'none',
fstype => 'swap',
ensure => mounted,
atboot => true,
device => '/swapfile',
options => 'sw',
}
应该管用。
如果这绝对必须用一句台词来完成(郑重声明,我还是反对),以下内容perl
应该有所帮助:
perl -pi -e 'BEGIN{$string = "/swapfile none swap sw 0 0"} s!^/swapfile.*!$string! && $x++;END{print "$string\n" unless $x}' /etc/fstab
为了清晰起见,分为几行:
perl -pi -e '
BEGIN{$string = "/swapfile none swap sw 0 0"}
s!^/swapfile.*!$string! && $x++; # Modify line if it exists
END{print "$string\n" unless $x} # Append it if it wasn't found
' /etc/fstab