Reputation: 488
I have several Apache vHost configurations across several hosts. I'm trying to write a Bash script that will iterate through each host and search the .conf
file on each one, pulling out the first (only the first) <VirtualHost>
block. I've tried writing a regex to match it, but it's just not working. Here's the code I've tried:
#!/bin/bash
egrep -o '(\<VirtualHost\>)(.*)(\<\/VirtualHost\>)' -m1
Since .*
doesn't match newlines, I even tried this:
#!/bin/bash
egrep -o '(\<VirtualHost\>)(.*[\S]*)(\<\/VirtualHost\>)' -m1
I still get nothing. :-(
I don't understand what I'm doing wrong here. Here is a sample of the data I'm trying to match:
<VirtualHost apache-frontend:80>
ServerAdmin [email protected]
ServerName domain.com
DocumentRoot /path/to/my/doc/root
RewriteEngine On
Include include.d/global/rewrite.conf
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
</VirtualHost>
<VirtualHost apache-frontend:80>
ServerAdmin [email protected]
ServerName domain.com
DocumentRoot /path/to/my/doc/root
RewriteEngine On
Include include.d/global/rewrite.conf
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
</VirtualHost>
<VirtualHost apache-frontend:80>
ServerAdmin [email protected]
ServerName domain.com
DocumentRoot /path/to/my/doc/root
RewriteEngine On
Include include.d/global/rewrite.conf
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
</VirtualHost>
Upvotes: 2
Views: 3085
Reputation: 3826
It is possible with grep
as seen here.
Example finding all lines matching in some html file:
grep -Pazo "(?s)<div\s+class=\"version\">.*?Version\s+[\.0-9]+"
Upvotes: 0
Reputation: 84343
Perl is part of the Linux Standard Base, and is also standard on OS X, so it should be highly available on most modern systems. Perl is great at multiline text tasks. For example:
$ perl -ne '
if (/VirtualHost/ ... m!/VirtualHost!) {
print unless /VirtualHost/;
exit if m!/VirtualHost!;
}' /tmp/corpus
This one-liner will:
Given your corpus, this will correctly yield:
ServerAdmin [email protected] ServerName domain.com DocumentRoot /path/to/my/doc/root RewriteEngine On Include include.d/global/rewrite.conf RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
Upvotes: 0
Reputation: 52132
With GNU sed:
$ sed -n '/<VirtualHost/,/<\/VirtualHost>/{p;/<\/VirtualHost>/q}' infile
<VirtualHost apache-frontend:80>
ServerAdmin [email protected]
ServerName domain.com
DocumentRoot /path/to/my/doc/root
RewriteEngine On
Include include.d/global/rewrite.conf
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
</VirtualHost>
-n
prevents printing/<VirtualHost/,/<\/VirtualHost>/
is an address range{p;/<\/VirtualHost>/q}
:
<\/VirtualHost>
, i.e., is the last line of the block we want, then quitTo run this with BSD sed, add one more semicolon:
sed -n '/<VirtualHost/,/<\/VirtualHost>/{p;/<\/VirtualHost>/q;}'
Upvotes: 1
Reputation: 8978
There is no guarantee that every platform have a PCRE compatible grep available. You can write a custom script which is guarantee to work on anywhere where python is available.
import re, sys
rx = '(?<=\<VirtualHost).*?\r?\n(.*?)(?=</VirtualHost>)'
data = ''.join(sys.stdin.readlines())
match = re.search(rx, data, re.DOTALL)
if match:
print(match.group(1))
You can use it as
cat your_vhost_file | python search.py
Where search.py is python file containing script posted above. After execution of script, you'll have content of first block as:
ServerAdmin [email protected]
ServerName domain.com
DocumentRoot /path/to/my/doc/root
RewriteEngine On
Include include.d/global/rewrite.conf
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L]
Note: This script can be easily adopted to list all matched sections in file.
Upvotes: 0
Reputation: 633
Actually you could use -B
option to print the context of the matching line, like this:
grep -E '</VirtualHost>' -m1 -B8 *yours.conf*
Upvotes: 1
Reputation: 380
this oneliner pulls only the first VirtualHost block from a config file:
awk '/<VirtualHost/,/<\/VirtualHost>/{print $0} /<\/VirtualHost>/{exit}' < vhostconf
Upvotes: 2