title: find all occurrences of pattern(s) after last occurrence of another pattern before line X
body: <p>Sounds a little bit complicated, but actually it isn't. Let's say we've got the following (apache2 config) file:</p>
  
  <pre><code>[...]
  
   &lt;VirtualHost 123.123.123.123:80&gt;
     ServerName one.domain.tld
     ServerAlias 1.domain.tld
  
     DocumentRoot "/path/to/anything"
     [...]
   &lt;/VirtualHost&gt;
  
   &lt;VirtualHost 321.321.321.321:80&gt;
     ServerName two.domain.tld
     ServerAlias 2.domain.tld
  
     DocumentRoot "/path/to/something/else"
     [...]
   &lt;/VirtualHost&gt;
  
   &lt;VirtualHost 123.123.123.123:443&gt;
     ServerName one.domain.tld
     ServerAlias 1.domain.tld
     ServerAlias secure.one.domain.tld
     ServerAlias secure.1.domain.tld
  
     DocumentRoot "/path/to/anything"
     [...]
   &lt;/VirtualHost&gt;
  
   &lt;VirtualHost 321.321.321.321:443&gt;
     ServerName two.domain.tld
     ServerAlias 2.domain.tld
     ServerAlias secure.two.domain.tld
     ServerAlias secure.2.domain.tld
  
     DocumentRoot "/path/to/another/something/else"
     [...]
   &lt;/VirtualHost&gt;
  
  [...]
  </code></pre>
  
  <hr>
  
  <p>I need to know the (sub)domains pointing to each document root. It's important for me to process each <code>DocumentRoot</code> seperately as I need to run certain commands in the for loop. I made an approach with <code>bash</code> and some additional programs like the following:</p>
  
  <pre><code>DOCROOTS="$(egrep -ni '^(DocumentRoot|[ ]*DocumentRoot|\t*DocumentRoot) ?=' ${HTCONF} |sed -r 's/(DocumentRoot|"|'"'"'| |   )//gI')"
  for DOCROOT in $(echo "${DOCROOTS}"); do
    LINE="$(printf ${DOCROOT} |cut -d':' -f1)"
    ROOT="$(printf ${DOCROOT} |cut -d':' -f2)"
    DOMAINS=$(sed "${LINE},\$d" ${HTCONF} |tac |sed '/VirtualHost/Iq' |tac |egrep -i 'ServerAlias|ServerName' |sed -r 's/(ServerName|ServerAlias| |   )//gI')
  
    [... rest of document root specific code goes here ...]
  done
  </code></pre>
  
  <p>Explanation:</p>
  
  <ol>
  <li>store all DocumentRoot definitions and their line number to variable <code>DOCROOTS</code></li>
  <li>for every line in <code>DOCROOTS</code> do:
  
  <ol>
  <li>set variable <code>LINE</code> to line number</li>
  <li>set variable <code>ROOT</code> to document root</li>
  <li><code>sed "${LINE},\$d" ${HTCONF}</code> - this deletes everything after <code>$LINE</code></li>
  <li><code>tac</code> - this works pretty much like <code>rev</code>, but not just reversing the content of one line, but the complete input</li>
  <li><code>sed '/VirtualHost/q'</code> - this deletes everything after the line containing <code>VirtualHost</code> case insensitively</li>
  <li><code>tac</code> - this reverses the complete input back to it's original order</li>
  <li><code>egrep -i 'ServerAlias|ServerName'</code> - this catches lines containing <code>ServerName</code> or <code>ServerAlias</code> only</li>
  <li><code>sed -r 's/(ServerName|ServerAlias| |  )//gI'</code> - this removes the <code>ServerName</code> and <code>ServerAlias</code> directive case insensitively as well as spaces and tabs.</li>
  </ol></li>
  </ol>
  
  <hr>
  
  <p>Desired output of a <code>printf "${ROOT}\n${DOMAINS}\n\n"</code> would then be something like this:</p>
  
  <pre><code>/path/to/anything
  one.domain.tld
  1.domain.tld
  
  /path/to/something/else
  two.domain.tld
  2.domain.tld
  
  /path/to/anything
  one.domain.tld
  1.domain.tld
  secure.one.domain.tld
  secure.1.domain.tld
  
  /path/to/another/something/else
  two.domain.tld
  2.domain.tld
  secure.two.domain.tld
  secure.2.domain.tld
  </code></pre>
  
  <hr>
  
  <p>Is there a better way to achieve this (maybe with <code>awk</code>)?</p>
  
  <p>Is <code>bash</code> the wrong way to do this? Should I consider using a proper scripting language? If so, which one would be recommendable?</p>