![按模式分割文件](https://linux22.com/image/91211/%E6%8C%89%E6%A8%A1%E5%BC%8F%E5%88%86%E5%89%B2%E6%96%87%E4%BB%B6.png)
有没有一种简单的方法可以将具有多个虚拟主机的 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
,则它们不会附加到下一节<VirtualHost
;csplit
不够聪明,无法做到这一点,更不用说弄清楚该评论是否适用于前面或后面的内容。
如果您想做一些更奇特的事情,例如在内容之后命名输出文件,您可以使用 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 编号的虚拟主机!