在带有多行变量的 shell 脚本中使用 sed

在带有多行变量的 shell 脚本中使用 sed

我使用 shell 脚本来设置不同类型的虚拟机。这些脚本通常包含多行变量,需要使用sed.

如果我像这样创建它们,一切都很好:

VAR="Config Line1\nConfig Line2\nConfig Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile

但这并不会使脚本变得非常可读,特别是因为文本块可能很长。

如果我这样写:

VAR="Config Line1
Config Line2
Config Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile

运行脚本时出现错误:sed: -e expression #1, char 31: unknown command:C'`

有没有办法使用sed这样声明的变量?

答案1

该命令的标准语法a是:

sed -e 'a\
first line\
  second line\
last line'

BSD(至少 FreeBSD 和 OS/X)sed去掉前导空格, 和需要-e解决一个错误。只要第一行非空,GNUsed就允许将第一行移到右侧之后。a\

因此,您需要预处理输入:

VAR='content with
multiple lines
  some with lead blanks
or even backslash\'

preprocessed_VAR=$(printf '%s\n' "$VAR" |
  sed 's/\\/&&/g;s/^[[:blank:]]/\\&/;s/$/\\/')

sed -i -e "/MatchingPattern/a\\
${preprocessed_VAR%?}" somefile

(在 FreeBSD 或 OS/X 上替换-i-i '')。

在 GNU/Linux 上并使用 GNU shell ( bash) 或zsh,您可以执行以下操作:

sed -i '/MatchingPattern/r /dev/stdin' <<< "$VAR"

这是可行的,因为bash使用zsh已删除的临时文件实现here-strings,并且Linux上的/dev/stdin被实现为文件的符号链接(这意味着它可以被打开多次,并且每次都在开始时打开)。

这里你也可以使用 GNUawk来代替:

(export VAR
gawk -i /usr/share/awk/inplace.awk '{print}; /MatchingPattern/{print ENVIRON["VAR"]}' somefile)

不使用-i inplaceas尝试首先从当前工作目录gawk加载inplace扩展(asinplace或),有人可能已经在其中植入了恶意软件。随系统提供的扩展inplace.awk的路径可能会有所不同,请参阅输出inplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

或者perl-i来自哪里):

(export VAR
perl -pi -e '$_ .= "$ENV{VAR}\n" if /MatchingPattern/' somefile)

答案2

该错误是由于sed附加命令a在实际的后面需要一个反斜杠a

使用 GNU sed

$ sed "/pattern/a\\$VAR" file.in >file.out

据我所知, BSDsed只能使用该命令将一行插入到文件中a,除非换行符被正确转义。

关于如何使用 BSD 解决此问题的密切相关答案sedhttp://unix.stackexchange.com/a/60322

相关内容