1

Is there an easy way to split, for example, apache vhost file with multiple vhost into 1 vhost per file?

Or something else, allowing to operate only one by one vhost to get grep output .

preferred solution in bash.

4
  • 3
    I don't know what one of those files look like. Please post input and expected output.
    – Kusalananda
    Jul 26, 2016 at 17:42
  • you mean you want it to be splited to {vhost_aa, vhost_ab, vhost_ac} or you want to split it to sections determined by context lines?
    – user172564
    Jul 26, 2016 at 17:49
  • I tried to tidy-up the question (grammar etc), however the 2nd paragraph made no sense to me, so I left it alone. Can you edit to make it clearer? Jul 26, 2016 at 17:58
  • 2
    Do you REALLY have to parse the apache configuration file WITH BASH? Or do you mean "from the bash command-line, how can I split the file?"
    – Jeff Schaller
    Jul 26, 2016 at 19:29

2 Answers 2

3

You can split files based on line contents with csplit. This is a POSIX command but the GNU version has some useful extensions. With GNU csplit (non-embedded Linux, Cygwin), here's how to split a file at each line that starts with <VirtualHost:

csplit -f 'virtualhost-' -b '%03d.conf' all-sites.conf '/^ *<VirtualHost /' '{*}'

Portably, this is clumsier. You have to count the number of occurrences, and the output file names end with the digit sequence.

csplit -f 'virtualhost-' all-sites.conf '/^ *<VirtualHost /' "{$(($(grep -c '^ *<VirtualHost <all-sites.conf') - 1))}"

Either way the first file contains everything up to the first <VirtualHost line; it may be empty. If there are comments just before a <VirtualHost line, they won't be attached to the following <VirtualHost section; csplit is not smart enough to do that, let alone figure out whether the comment applies to the preceding or following content.

If you want to do something fancier, such as name the output files after the content, you can use awk. The csplit utility is convenient sometimes, but awk can do everything it can do without much difficulty.

awk '
  BEGIN {output_file = "preamble.conf"}
  /^ *<VirtualHost *[^ >]/ {
      output_file = "virtualhost-" sub(/ *[:>].*/, "", sub(/^ *<VirtualHost */, "", $0) ".conf";
  }
  {print >output_file}
' all-sites.conf
1

This is working here, but it is not perfect:

#!/bin/bash


i=1
echo >vhost_${i}.conf
while IFS= read -r lin; do
        case $lin in 
        \<VirtualHost*\>)
                true
        ;;
        esac

        echo "$lin" >>vhost_${i}.conf 

        case $lin in 
        \</VirtualHost\>)
            i=$((i+1))
            echo >>vhost_${i}.conf
        ;;
        esac

done

You need to pipe the contents of the file to this script like that:

cat thenicefile.conf | thisscript 

And you probably will have vhosts numbered from thenicefile.conf!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .