按模式分割文件

按模式分割文件

有没有一种简单的方法可以将具有多个虚拟主机的 apache 虚拟主机文件拆分为每个文件 1 个虚拟主机?

或者其他什么,允许仅操作一个虚拟主机以获得 grep 输出。

bash 中的首选解决方案。

答案1

您可以根据行内容拆分文件csplit。这是一个POSIX命令但是GNU版本有一些有用的扩展。使用 GNU csplit(非嵌入式 Linux、Cygwin),以下是如何在以 开头的每一行分割文件<VirtualHost

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

可移植的是,这比较笨拙。您必须计算出现的次数,并且输出文件名以数字序列结尾。

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

无论哪种方式,第一个文件都包含第一行之前的所有内容<VirtualHost;它可能是空的。如果一行之前有注释<VirtualHost,则它们不会附加到下一节<VirtualHostcsplit不够聪明,无法做到这一点,更不用说弄清楚该评论是否适用于前面或后面的内容。

如果您想做一些更奇特的事情,例如在内容之后命名输出文件,您可以使用 awk。 csplit 实用程序有时很方便,但 awk 可以轻松完成它能做的所有事情。

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

答案2

这在这里可行,但并不完美:

#!/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

您需要将文件的内容通过管道传输到此脚本,如下所示:

cat thenicefile.conf | thisscript 

您可能会有从 thenicefile.conf 编号的虚拟主机!

相关内容