egrep匹配多行

时间:2016-03-11 01:00:20

标签: regex bash grep

我在多个主机上有几个Apache vHost配置。我正在尝试编写一个Bash脚本,该脚本将遍历每个主机并搜索每个主机上的.conf文件,从中拉出第一个(仅第一个)<VirtualHost>块。我试过写一个正则表达式来匹配它,但它只是不起作用。这是我尝试过的代码:

    #!/bin/bash
    egrep -o '(\<VirtualHost\>)(.*)(\<\/VirtualHost\>)' -m1

由于.*与换行符不匹配,我甚至试过了:

    #!/bin/bash
    egrep -o '(\<VirtualHost\>)(.*[\S]*)(\<\/VirtualHost\>)' -m1

我仍然一无所获。 : - (

我不明白我在这里做错了什么。以下是我试图匹配的数据示例:

    <VirtualHost apache-frontend:80>
            ServerAdmin     mysite@domain.com
            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     mysite@domain.com
            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     mysite@domain.com
            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>

6 个答案:

答案 0 :(得分:2)

此oneliner仅从配置文件中提取第一个VirtualHost块:

awk '/<VirtualHost/,/<\/VirtualHost>/{print $0} /<\/VirtualHost>/{exit}' < vhostconf

答案 1 :(得分:1)

实际上你可以使用-B选项打印匹配行的上下文,如下所示:

grep -E '</VirtualHost>' -m1 -B8 *yours.conf*

答案 2 :(得分:1)

使用GNU sed:

$ sed -n '/<VirtualHost/,/<\/VirtualHost>/{p;/<\/VirtualHost>/q}' infile
    <VirtualHost apache-frontend:80>
            ServerAdmin     mysite@domain.com
            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阻止打印
  • /<VirtualHost/,/<\/VirtualHost>/是地址范围
  • 对于范围内的每一行,请执行{p;/<\/VirtualHost>/q}
    • 打印行
    • 如果该行与<\/VirtualHost>匹配,即,是我们想要的块的最后一行,则退出

要使用BSD sed运行此命令,请再添加一个分号:

sed -n '/<VirtualHost/,/<\/VirtualHost>/{p;/<\/VirtualHost>/q;}'

答案 3 :(得分:0)

无法保证每个平台都具有可与PCRE兼容的grep。您可以编写一个自定义脚本,以保证在python可用的任何地方工作。

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))

您可以将其用作

cat  your_vhost_file | python search.py

其中search.py​​是包含上面发布的脚本的python文件。执行脚本后,您将第一个块的内容设为:

        ServerAdmin     mysite@domain.com
        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]

注意:可以轻松采用此脚本列出文件中所有匹配的部分。

答案 4 :(得分:0)

使用Perl

Perl是Linux标准库的一部分,也是OS X的标准配置,因此它应该在大多数现代系统上都可用。 Perl非常适合多线文本任务。例如:

$ perl -ne '
      if (/VirtualHost/ ... m!/VirtualHost!) {
          print unless /VirtualHost/;
          exit if m!/VirtualHost!;
      }' /tmp/corpus

这个单行将:

  1. 循环输入文件,直到找到VirtualHost块。
  2. 打印该块中的每一行,不包括起始或结束块标记。
  3. 当脚本看到VirtualHost块结束时退出脚本,确保它只显示第一个块。
  4. 鉴于你的语料库,这将正确地产生:

               ServerAdmin     mysite@domain.com
               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]
    

答案 5 :(得分:0)

grep可能与here一样。

在某个html文件中查找所有匹配行的示例:

grep -Pazo "(?s)<div\s+class=\"version\">.*?Version\s+[\.0-9]+"