在文件中用字符串替换或附加一行

fra*_*ank 4 sed text-processing

我正在寻找有关如何在文件中搜索字符串的一部分并替换整行或将该字符串附加到该文件(如果未找到)的建议。我现在用 sed “玩”了一段时间,但无法让它按预期工作。

我需要补充:

/swapfile   none    swap    sw    0   0
Run Code Online (Sandbox Code Playgroud)

/etc/fstab(在Ubuntu 14.04 - Trusty Tahr 上)。

状况:

  • 如果/swapfile中存在以开头的任何行/etc/fstab,请删除该行并替换为上面提供的字符串
  • 如果/swapfile发现多于一行,将它们全部删除并将上面的字符串附加到文件末尾
  • 如果 中不/swapfile存在/etc/fstab,则将字符串附加到/etc/fstab
  • 该命令不得显示控制台输出,并且必须是“单行”(由于 puppet 的自动化目的)

我相信这是可能的,但我只是没有找到有关以我需要的方式使用 sed 的相关教程。

我使用过,sudo sed -i '$a/swapfile none swap sw 0 0' /etc/fstab 但这只会附加字符串:(

Gil*_*il' 5

你可以用 sed 做到这一点——它是图灵完备的。但它不是完成这项工作的最佳工具。Sed 没有一种方便的方式来记住它已经被替换了。

您可以相对轻松地使用 sed 将所有以 开头的行清空/swapfile,并在末尾添加一个新行:

sed -i '$! s/^\/swapfile[\t ]//; $s/\(^\/swapfile.*\)\?$/\n\/swapfile none swap sw/' /etc/fstab
Run Code Online (Sandbox Code Playgroud)

但除此之外,我们很快就进入了一个领域,我不会将这样的 sed 代码留给另一个系统管理员来维护,尤其是当一个简单、可读的 shell 命令组合可以做得更好时:

{ </etc/fstab grep -v '/swapfile[\t ]'; echo '/swapfile none swap sw'; } >/etc/fstab.new && mv /etc/fstab.new /etc/fstab
Run Code Online (Sandbox Code Playgroud)

如果您想保留该/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
Run Code Online (Sandbox Code Playgroud)