Sed Replace A Multi-Line String
Example
mkdir -p ${HOME}/Documents/sed_playground
tee -a ${HOME}/Documents/sed_playground/000-default.conf >/dev/null <<EOF
#
#This is some test comments
# Skip this
#
<Directory "/var/www/cgi-bin">
AllowOverride None
Options +ExecCGI
AddHandler cgi-script .cgi .pl
Require all granted
</Directory>
EOF
| |
| |
APACHE_CONF_FILE="${HOME}/Documents/sed_playground/000-default.conf"
DIRECTORY_FIND_LEAD_EXP='<Directory "\/var\/www\/cgi-bin">'
| |
| |
DIRECTORY_FIND_FULL_EXP=$(cat <<EOF
${DIRECTORY_FIND_LEAD_EXP}\n\
[ ]*AllowOverride None\n\
[ ]*Options +ExecCGI\n\
[ ]*AddHandler cgi-script \.cgi \.pl\n\
[ ]*Require all granted\n\
<\/Directory>
EOF
)
|
DIRECTORY_FILL_FULL_EXP=$(cat <<EOF
#<Directory "\/var\/www\/cgi-bin">\n\
#AllowOverride None\n\
#Options +ExecCGI\n\
#AddHandler cgi-script \.cgi \.pl\n\
#Require all granted\n\
#<\/Directory>
EOF
)
|
| |
Complex: echo "complex"
echo "sedding"
sed -i "/${DIRECTORY_FIND_LEAD_EXP}/{N;N;N;N;N;s|${DIRECTORY_FIND_FULL_EXP}|${DIRECTORY_FILL_FULL_EXP}|}" ${APACHE_CONF_FILE}
| |
| |
Simple: echo "simple"
echo "sedding"
sed -z "s|${DIRECTORY_FIND_FULL_EXP}|${DIRECTORY_FILL_FULL_EXP}|" -i ${APACHE_CONF_FILE}
| |
| |
${HOME}/Documents/sed_playground/000-default.conf #
#This is some test comments
# Skip this
#
<Directory "/var/www/cgi-bin">
AllowOverride None
Options +ExecCGI
AddHandler cgi-script .cgi .pl
Require all granted
</Directory>
|
${HOME}/Documents/sed_playground/000-default.conf #
#This is some test comments
# Skip this
#
#<Directory "/var/www/cgi-bin">
#AllowOverride None
#Options +ExecCGI
#AddHandler cgi-script .cgi .pl
#Require all granted
#</Directory>
|
| |
| |
| |
DIRECTORY_FIND_FULL_EXP=$(cat <<EOF
<Directory "/var/www/cgi-bin">\n\
[ ]*AllowOverride None\n\
[ ]*Options +ExecCGI\n\
[ ]*AddHandler cgi-script .cgi .pl\n\
[ ]*Require all granted\n\
</Directory>
EOF
)
|
DIRECTORY_FILL_FULL_EXP=$(cat <<EOF
#<Directory "/var/www/cgi-bin">\n\
#AllowOverride None\n\
#Options +ExecCGI\n\
#AddHandler cgi-script .cgi .pl\n\
#Require all granted\n\
#</Directory>
EOF
)
|
Explanation
DIRECTORY_FIND_LEAD_EXP='<Directory "\/var\/www\/cgi-bin">'
Special characters must be escaped with a backslash\
.[ ]*
This will match 0 or many whitespaces. Standard RegEx notationsed -i "/${DIRECTORY_FIND_LEAD_EXP}/{
This will search the file, line-by-line, for${DIRECTORY_FIND_LEAD_EXP}
<Directory "/var/www/cgi-bin">
. Note that the search pattern must not contain newline. If, and only if, sed finds${DIRECTORY_FIND_LEAD_EXP}
in the file, then it will proceed with executing the sub-code within the curly braces{}
. It will start from the pattern matching line of file.N;N;N;N;N;
N tells sed to read the next line after the pattern and attach it to current line. It is important to understand that sed is designed to replace only 1 line at a time, so N will basically force sed to read 2 lines and consider them as a single line with a single newline\n
between the two. The newline in the second line will be ignored. By chaining 5 Ns, we are instructing sed to read 6 lines of the file starting with the pattern matching line.s|${DIRECTORY_FIND_FULL_EXP}|${DIRECTORY_FILL_FULL_EXP}|
Replace${DIRECTORY_FIND_FULL_EXP}
with${DIRECTORY_FILL_FULL_EXP}
. Note the presence of newlines in the variables. Understanding this part will take some trial and error.
References
| ||