Tom
Tom

Reputation: 9653

How to insert text after a specific line with bash?

I want to insert a block of text after a specific line that starts with the word DocumentRoot.

This is the original text (file named li1023-68.members.linode.com):

<VirtualHost *:80>
    ServerName li1023-68.members.linode.com
    DocumentRoot /srv/www/li1023-68.members.linode.com/public_html/
    ErrorLog /srv/www/li1023-68.members.linode.com/logs/error.log
    CustomLog /srv/www/li1023-68.members.linode.com/logs/access.log combined
</VirtualHost>

This is what I want to achieve:

<VirtualHost *:80>
    ServerName li1023-68.members.linode.com
    DocumentRoot /srv/www/li1023-68.members.linode.com/public_html/
    <Directory /srv/www/$path/public_html>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
    </Directory>
    ErrorLog /srv/www/li1023-68.members.linode.com/logs/error.log
    CustomLog /srv/www/li1023-68.members.linode.com/logs/access.log combined
</VirtualHost>

I tried doing so with the following code and it doesn't work. $path holds the name of the text that should be modified (ie li1023-68.members.linode.com):

value="<Directory /srv/www/$path/public_html>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>"

sed '/DocumentRoot.*$/a $value' /etc/apache2/sites-available/$path
while read line
do
        echo $line
        echo $line | grep -q "DocumentRoot"
        [ $? -eq 0 ] && echo "$value"
done < $path

What am I missing?

Upvotes: 2

Views: 781

Answers (1)

Adam Liss
Adam Liss

Reputation: 48330

The single quotes prevent the shell from expanding $value, and you need to use sed's s (substitute) command:

sed -i "s!DocumentRoot.*!&\n$value!" /etc/apache2/sites-available/$path

The -i argument tells sed to do in-place substitution; that is, change the file without sending the output to stdout, and you don't need the $ at the end of the search string.

But sed will see the first newline in $value and assume it terminates the command, which is not what you want. Replace the newlines in $value with \n like this:

value="<Directory /srv/www/$path/public_html>\nOptions Indexes FollowSymLinks MultiViews\n..."

[Edit: Note, also that it's customary to delimit the pattern and replacement with slashes, but then sed will assume the slashes in $value are delimiters! So we can use exclamation points (or any other unused character) instead.]

Then you won't need the loop at all.

If you use the loop instead (you don't need both), remember to specify the entire filename:

done < /etc/apache2/sites-available/$path

Upvotes: 2

Related Questions