Trying to write a heredoc into an existing file using Sed in bash

那年仲夏 提交于 2019-12-11 05:47:12

问题


I'm attempting to write a heredoc at the top of my php.ini file directly under the [PHP] line. I'm also attempting to do it assuming the following conditions:

  1. [PHP] might not be at the very top (in other use cases, it would be nice to know how to put a heredoc anywhere in a file after something, so specifying 'line 2' isn't really useful
  2. The heredoc has to be contained in the file. No use of sed where another file is opened and read into the existing file
  3. Assume there is only one instance of the [PHP] identifier. In this learning exercise, I'm not worried about iterating a list, or Sed / Awk finding more than one instance of my search string
  4. I'd really like to have each item on its own line just like in the heredoc

Script:

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

In every iteration I've tried, I simply end up with a php.ini looking like this:

[PHP]
$myvar

Or, I get the following error:

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

My goal is:

[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

回答1:


While this task can be done with sed, sed is not optimal. It does not support variables. Anytime one has to encorporate shell variables within a sed command, one opens potential security flaws. Awk, by contrast, is well-suited to this task. If you have GNU awk (gawk), try:

$ 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

The result is:

$ 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 or other non-GNU awk

If your awk does not support GNU's -i inplace option, then replace the awk line with:

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

Notes

myvar can be defined directly, as shown above, without using cat or here-docs.




回答2:


You can use the sed r command which inserts text from a file, but use process substitution to replace the filename with the 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



回答3:


Sometimes the good old ed could be also helpful. Like:

(
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

EDIT - simpler (nothing "dynamic") :)

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


来源:https://stackoverflow.com/questions/47582028/trying-to-write-a-heredoc-into-an-existing-file-using-sed-in-bash

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!