1

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
CarComp
  • 1,929
  • 1
  • 21
  • 47

2 Answers2

2

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.

John1024
  • 109,961
  • 14
  • 137
  • 171
  • I chose this answer because of elaboration on using the correct tool. Thanks for steering me towards Awk. I assumed Awk and Sed were basically the same thing. Like VI or Emacs. I'm going to explore using it more. Sed is 'awk'ward sometimes. – CarComp Dec 01 '17 at 13:25
1

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
Cole Tierney
  • 9,571
  • 1
  • 27
  • 35
  • After I upvoted this, I found this doesn't work as is. cat needs arg - and if "N" command required after "r". I corrected your script as https://pastebin.com/F20vgr7K . (see also my newly written answer of referred question https://stackoverflow.com/a/56182135/26736 ). Anyway your code helps me because I don't know "<(..) " bash trick. Thanks ! – benok May 17 '19 at 08:19