【问题标题】:Trying to write a heredoc into an existing file using Sed in bash尝试在 bash 中使用 Sed 将 heredoc 写入现有文件
【发布时间】:2017-12-01 09:33:21
【问题描述】:

我正在尝试在我的 php.ini 文件顶部直接在 [PHP] 行下编写一个heredoc。我也在尝试假设以下条件:

  1. [PHP] 可能不在最顶端(在其他用例中,很高兴知道如何将 heredoc 放在文件中的任何位置之后,因此指定“第 2 行”并不是真的有用李>
  2. heredoc 必须包含在文件中。在打开另一个文件并读入现有文件时不使用 sed
  3. 假设只有一个 [PHP] 标识符实例。在这个学习练习中,我不担心迭代列表,也不担心 Sed/Awk 会找到多个我的搜索字符串的实例
  4. 我真的很想像在 heredoc 中一样将每个项目放在单独的行中

脚本:

myvar=$(cat << END_HEREDOC
[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
xdebug.remote_host = localhost
xdebug.idekey = "PHPSTORM"
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.show_local_vars=0
xdebug.var_display_max_data=10000
xdebug.var_display_max_depth=20
xdebug.show_exception_trace=0
xdebug.remote_handler=dbgp
END_HEREDOC
)

echo ${myvar}

sed -i "/\[PHP\]'/${myvar}/'" php.ini

在我尝试过的每一次迭代中,我最终都会得到一个看起来像这样的 php.ini:

[PHP]
$myvar

或者,我收到以下错误:

sed: -e expression #1, char 15: unknown command: `e'

我的目标是:

[PHP]

[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
xdebug.remote_host = localhost
xdebug.idekey = "PHPSTORM"
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.show_local_vars=0
xdebug.var_display_max_data=10000
xdebug.var_display_max_depth=20
xdebug.show_exception_trace=0
xdebug.remote_handler=dbgp

【问题讨论】:

  • sed命令的格式是sed "/a/b/"不应该是sed "s/a/b/"吗?

标签: bash sed heredoc


【解决方案1】:

虽然可以使用 sed 完成此任务,但 sed 并不是最佳选择。它不支持变量。任何时候必须在 sed 命令中包含 shell 变量,就会打开潜在的安全漏洞。相比之下,Awk 非常适合这项任务。如果您有 GNU awk (gawk),请尝试:

$ cat script.sh
myvar='
[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
xdebug.remote_host = localhost
xdebug.idekey = "PHPSTORM"
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.show_local_vars=0
xdebug.var_display_max_data=10000
xdebug.var_display_max_depth=20
xdebug.show_exception_trace=0
xdebug.remote_handler=dbgp
'
awk -i inplace -v x="$myvar" '{print} /\[PHP\]/{print x}' php.ini

结果是:

$ cat php.ini
[PHP]

[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
xdebug.remote_host = localhost
xdebug.idekey = "PHPSTORM"
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.show_local_vars=0
xdebug.var_display_max_data=10000
xdebug.var_display_max_depth=20
xdebug.show_exception_trace=0
xdebug.remote_handler=dbgp

BSD/OSX 或其他非 GNU awk

如果您的 awk 不支持 GNU 的 -i inplace 选项,则将 awk 行替换为:

awk -v x="$myvar" '{print} /\[PHP\]/{print x}' php.ini >tmp && mv tmp php.ini

注意事项

myvar可以直接定义,如上图,不用cat或者here-docs。

【讨论】:

  • 我之所以选择这个答案是因为详细说明了使用正确的工具。感谢您引导我走向 Awk。我认为 Awk 和 Sed 基本上是一回事。像 VI 或 Emacs。我将更多地探索使用它。 Sed 有时会很“尴尬”。
【解决方案2】:

您可以使用 sed r 命令从文件中插入文本,但使用进程替换将文件名替换为 heredoc:

#!/bin/bash

sed -i '' '/\[PHP]/r '<(cat << END_HEREDOC
[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
xdebug.remote_host = localhost
xdebug.idekey = "PHPSTORM"
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_enable=1
xdebug.remote_port=9000
xdebug.show_local_vars=0
xdebug.var_display_max_data=10000
xdebug.var_display_max_depth=20
xdebug.show_exception_trace=0
xdebug.remote_handler=dbgp
END_HEREDOC
) php.ini

【讨论】:

  • 在我对此表示赞同后,我发现这不起作用。 cat 需要 arg - 如果在“r”之后需要“N”命令。我将您的脚本更正为 pastebin.com/F20vgr7K 。 (另请参阅我对提到的问题stackoverflow.com/a/56182135/26736 的新书面回答)。无论如何,您的代码对我有帮助,因为我不知道 "
【解决方案3】:

有时,好老的ed 也可能会有所帮助。喜欢:

(
printf '%s\n' '/^\[PHP\]/' i

cat <<'END_HEREDOC'
[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
...
END_HEREDOC

printf '%s\n' . w q
) | ed -s php.ini > /dev/null

编辑 - 更简单(没有“动态”):)

ed -s php.ini >/dev/null <<'END_HEREDOC'
/^\[PHP\]/
i
[xdebug]
zend_extension=/usr/lib/php/20151226/xdebug.so
.
w
q
END_HEREDOC

【讨论】:

  • 一般来说,这种动态脚本生成是个坏主意。例如,如果 . w q 实际上是 here 文档中的一行,则脚本会提前终止。最好使用可以接受适当参数的工具。
  • 一般来说,这种动态脚本生成是个坏主意。例如,如果 . w q 实际上是 here 文档中的一行,则脚本会提前终止。最好使用可以接受适当参数的工具。
  • @chepner 当然,一般来说你是对的,但在这种情况下,插入的文本 不是随机的 - 所以,在这种情况下 - 可以安全使用.. . 是的,阅读一些随机文本(而不是heredoc)可能是不安全的——但那是另一种情况......更重要的是,以上所有内容都可以简化为仅包含所有@的one heredeoc 987654326@ 命令也...(没有任何 printf)
猜你喜欢
  • 2011-02-26
  • 2016-03-26
  • 2019-08-05
  • 2014-08-29
  • 2020-05-06
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多