sed 在匹配单行字符串后追加多行字符串
sed append multi-line string after matching a single line string
如果可能,我想将 sed
用于此解决方案。这是我的情况:
我有一个多行字符串,将通过外部方式提供给 sed
- 可能是人偶 shell exec 或 bash 脚本。字符串看起来像:
$string = 'blah blah blah\nblahblah\nblah blah blah\n\n'
我想要 运行 一个 sed
命令,在找到匹配后追加这个字符串 -
sed -i "/^\[org\/gnome\/login-screen\]/a banner-message-text='$string'" /etc/dconf/db/gdm.d/00-mybanner
问题在于 sed
将 \n
字符解释为换行符。请注意,我意识到我在 sed
命令中声明 $string
变量的方式可能会有所不同,具体取决于它的执行方式,但即使在命令行上手动键入字符串也会产生多行输出。所以文件最终看起来像:
[org/gnome/login-screen]
banner-message-text='blah blah blah
blablah
blah blah blah
'
banner-message-enable=true
这会导致 dconf update
抛出错误。我希望文件看起来像:
[org/gnome/login-screen]
banner-message-text='blah blah blah\nblablah\nblah blah blah\n\n'
banner-message-enable=true
但我似乎无法让 sed
停止自己解释 \n
。
谢谢!
编辑 - 使用 Puppet 实现解决方案 (@tom-fenech) 的完整上下文:
$banner_msg = 'blah blah blah\nblahblah\nblah blah blah\n\n'
$comply_cmd = "find /etc/dconf/db/gdm.d -maxdepth 1 -type f -print0 | xargs -0 sed -i '/^banner-message-text=/d' || /bin/true && \
(grep -q \"^\[org/gnome/login-screen\]\" /etc/dconf/db/gdm.d/99-banner && \
sed -i \"/^\[org\/gnome\/login-screen\]/a banner-message-text='$(printf '%q' \"${banner_msg}\")'\" /etc/dconf/db/gdm.d/99-banner) || \
(echo -e \"\n\[org/gnome/login-screen]\" >> /etc/dconf/db/gdm.d/99-banner && \
echo \"banner-message-text='${banner_msg}'\" >> /etc/dconf/db/gdm.d/99-banner)"
$unless_cmd = "grep -q \"^banner-message-text='$(printf '%q' \"${banner_msg}\")'$\" /etc/dconf/db/gdm.d/99-banner"
exec { 'gdm-banner-msg':
path => '/sbin:/bin:/usr/sbin:/usr/bin',
umask => '022',
provider => shell,
command => $comply_cmd,
unless => $unless_cmd,
notify => Exec['dconf-update'],
}
谢谢大家!
您需要转义反斜杠:
$ string='blah blah blah\nblahblah\nblah blah blah\n\n'
$ echo $string
blah blah blah\nblahblah\nblah blah blah\n\n
$ cat foo.txt
foo
baz
test
$ sed -i "/^foo/a bar='$string'" foo.txt
$ cat foo.txt
foo
bar='blah blah blah\nblahblah\nblah blah blah\n\n'
baz
test
$
使用 printf
和 %q
格式说明符。这会为您处理转义:
$ echo "$string"
blah blah blah\nblahblah\nblah blah blah\n\n
$ printf '%q' "$string"
blah\ blah\ blah\nblahblah\nblah\ blah\ blah\n\n
来自man bash
:
%q
causes printf
to output the corresponding argument in a format
that can be reused as shell input.
这意味着空格也被反斜杠转义了,但这没有坏处。
正在测试:
$ cat file
[org/gnome/login-screen]
$ sed "/^\[org\/gnome\/login-screen\]/a banner-message-text='$(printf '%q' "$string")'" file
[org/gnome/login-screen]
banner-message-text='blah blah blah\nblahblah\nblah blah blah\n\n'
准备初始配置文件:
echo -e "[org/gnome/login-screen]\nbanner-message-enable=true"> /etc/dconf/db/gdm.d/00-mybanner
cat /etc/dconf/db/gdm.d/00-mybanner
[org/gnome/login-screen]
banner-message-enable=true
插入新横幅消息而不解释 \n 字符:
string='blah blah blah\nblahblah\nblah blah blah\n\n'; sed -i "/^\[org\/gnome\/login-screen\]/a banner-message-text=\'$string\'" /etc/dconf/db/gdm.d/00-mybanner
查看结果:
cat /etc/dconf/db/gdm.d/00-mybanner
[org/gnome/login-screen]
banner-message-text='blah blah blah\nblahblah\nblah blah blah\n\n'
banner-message-enable=true
要点是:在字符串中的每个 \n 前添加一个 斜线。这将阻止 sed 解释 \n 字符。
如果可能,我想将 sed
用于此解决方案。这是我的情况:
我有一个多行字符串,将通过外部方式提供给 sed
- 可能是人偶 shell exec 或 bash 脚本。字符串看起来像:
$string = 'blah blah blah\nblahblah\nblah blah blah\n\n'
我想要 运行 一个 sed
命令,在找到匹配后追加这个字符串 -
sed -i "/^\[org\/gnome\/login-screen\]/a banner-message-text='$string'" /etc/dconf/db/gdm.d/00-mybanner
问题在于 sed
将 \n
字符解释为换行符。请注意,我意识到我在 sed
命令中声明 $string
变量的方式可能会有所不同,具体取决于它的执行方式,但即使在命令行上手动键入字符串也会产生多行输出。所以文件最终看起来像:
[org/gnome/login-screen]
banner-message-text='blah blah blah
blablah
blah blah blah
'
banner-message-enable=true
这会导致 dconf update
抛出错误。我希望文件看起来像:
[org/gnome/login-screen]
banner-message-text='blah blah blah\nblablah\nblah blah blah\n\n'
banner-message-enable=true
但我似乎无法让 sed
停止自己解释 \n
。
谢谢!
编辑 - 使用 Puppet 实现解决方案 (@tom-fenech) 的完整上下文:
$banner_msg = 'blah blah blah\nblahblah\nblah blah blah\n\n'
$comply_cmd = "find /etc/dconf/db/gdm.d -maxdepth 1 -type f -print0 | xargs -0 sed -i '/^banner-message-text=/d' || /bin/true && \
(grep -q \"^\[org/gnome/login-screen\]\" /etc/dconf/db/gdm.d/99-banner && \
sed -i \"/^\[org\/gnome\/login-screen\]/a banner-message-text='$(printf '%q' \"${banner_msg}\")'\" /etc/dconf/db/gdm.d/99-banner) || \
(echo -e \"\n\[org/gnome/login-screen]\" >> /etc/dconf/db/gdm.d/99-banner && \
echo \"banner-message-text='${banner_msg}'\" >> /etc/dconf/db/gdm.d/99-banner)"
$unless_cmd = "grep -q \"^banner-message-text='$(printf '%q' \"${banner_msg}\")'$\" /etc/dconf/db/gdm.d/99-banner"
exec { 'gdm-banner-msg':
path => '/sbin:/bin:/usr/sbin:/usr/bin',
umask => '022',
provider => shell,
command => $comply_cmd,
unless => $unless_cmd,
notify => Exec['dconf-update'],
}
谢谢大家!
您需要转义反斜杠:
$ string='blah blah blah\nblahblah\nblah blah blah\n\n'
$ echo $string
blah blah blah\nblahblah\nblah blah blah\n\n
$ cat foo.txt
foo
baz
test
$ sed -i "/^foo/a bar='$string'" foo.txt
$ cat foo.txt
foo
bar='blah blah blah\nblahblah\nblah blah blah\n\n'
baz
test
$
使用 printf
和 %q
格式说明符。这会为您处理转义:
$ echo "$string"
blah blah blah\nblahblah\nblah blah blah\n\n
$ printf '%q' "$string"
blah\ blah\ blah\nblahblah\nblah\ blah\ blah\n\n
来自man bash
:
%q
causesprintf
to output the corresponding argument in a format that can be reused as shell input.
这意味着空格也被反斜杠转义了,但这没有坏处。
正在测试:
$ cat file
[org/gnome/login-screen]
$ sed "/^\[org\/gnome\/login-screen\]/a banner-message-text='$(printf '%q' "$string")'" file
[org/gnome/login-screen]
banner-message-text='blah blah blah\nblahblah\nblah blah blah\n\n'
准备初始配置文件:
echo -e "[org/gnome/login-screen]\nbanner-message-enable=true"> /etc/dconf/db/gdm.d/00-mybanner
cat /etc/dconf/db/gdm.d/00-mybanner
[org/gnome/login-screen]
banner-message-enable=true
插入新横幅消息而不解释 \n 字符:
string='blah blah blah\nblahblah\nblah blah blah\n\n'; sed -i "/^\[org\/gnome\/login-screen\]/a banner-message-text=\'$string\'" /etc/dconf/db/gdm.d/00-mybanner
查看结果:
cat /etc/dconf/db/gdm.d/00-mybanner
[org/gnome/login-screen]
banner-message-text='blah blah blah\nblahblah\nblah blah blah\n\n'
banner-message-enable=true
要点是:在字符串中的每个 \n 前添加一个 斜线。这将阻止 sed 解释 \n 字符。