如果找到特定文本,则打印标签之间的文本(包括)

如果找到特定文本,则打印标签之间的文本(包括)

我的任务是从多个 Apache 服务器中提取数据。任务是打印出:

<Directory ...>
  ...
</Directory>

其中 +ExecCGI 位于其中。我举个例子来说明一下。假设 Apache 配置文件有许多目录部分,如下所示:

<Directory /var/www/site1/htdocs>
  Options +ExecCGI
  ...
  ...
</Directory>
...
...
...
<Directory /var/www/site1/Promo>
  Options -ExecCGI
  ...
  ...
</Directory>

从上面,我只想得到以下输出:

<Directory /var/www/site1/htdocs>
  Options +ExecCGI
  ...
  ...
</Directory>

我搜索了论坛并找到了一些帖子,其中人们提出了如何打印标签之间的整个部分的问题(我知道如何做到这一点),或者在找到时更改某些文本(同样,我知道如何做到这一点) )。

我将把 +ExecCGI 更改为 -ExecCGI,但更改需要经过审核过程,因此这个问题是这样我可以提取这些数据的。

答案1

perl -l -0777 -ne 'for (m{<Directory.*?</Directory>}gs) {print if /\+ExecCGI/}'

或者使用 GNU grep

grep -zPo '(?s)<Directory(?:.(?!</Directory))*?\+ExecCGI.*?</Directory>'

答案2

你也可以使用awk

awk 'BEGIN{RS="</Directory>\n"; ORS=RS} /\+ExecCGI/ {print}' file

答案3

如果您可以使用perl,这里有一个解决方案:

$ perl -nle '
    if (/<Directory/) {
        $flag = 1;
    }
    push @a, $_ if $flag;
    if (/<\/Directory/) {
        $flag = 0;
        if (grep {$_ =~ /\+ExecCGI/} @a) {
            push @f, @a;
        }
        @a = ();
     }
END {
    print join "\n", @f;
}' file
<Directory /var/www/site1/htdocs>
  Options +ExecCGI
  ...
  ...
</Directory>

解释

  • 每次我们看到<Directory,我们就设定$flag = 1
  • 如果$flag为 true(1 在布尔上下文中表示 true),我们将当前条目推送到 array @a
  • 如果我们看到</Directory,这意味着我们完成了该块,我们检查块是否包含+ExecCGIstring grep {$_ =~ /\+ExecCGI/,然后我们推@a送到@f
  • 设置@a为空数组以处理另一个块。

答案4

这是 Bash 中的一个示例(您应该能够在几乎任何语言中执行类似的操作):

$ cat test.sh
#!/bin/bash

DIR=0
BLOCK=''
while read line
do
    if [ $DIR -eq 0 ] ; then
        if [[ $(echo $line | grep -i '<Directory') ]] ; then
            DIR=1
            BLOCK="$line"
        fi
    else
        BLOCK="$BLOCK\n$line"
        if [[ $(echo $line | grep -i '</Directory') ]] ; then
            if [[ $(echo $BLOCK | grep -i 'Options.*+ExecCGI') ]] ; then
                echo -e $BLOCK
            fi
            DIR=0
            BLOCK=""
        fi
    fi
done

基本上,我们只是在进行过程中保存该块,然后grepping查看它是否包含我们的模式。

它非常简单,并且可能会在某些边缘情况下出现问题(echo -e例如,如果您的配置文件中有 \ ,它可能会造成混淆),但您可以扩展基本思想来处理它们。

使用示例:

$ cat test.conf
<Directory /var/www/site1/htdocs>
  Options +ExecCGI
  1
  2
</Directory>
3
4
5
<Directory /var/www/site1/Promo>
  Options -ExecCGI
  6
  7
</Directory>
<Directory /var/www/site1/htdocs>
  Options -Whatever +ExecCGI
  8
  9
</Directory>

$ cat test.conf | bash test.sh
<Directory /var/www/site1/htdocs>
Options +ExecCGI
1
2
</Directory>
<Directory /var/www/site1/htdocs>
Options -Whatever +ExecCGI
8
9
</Directory>

相关内容