特定のテキストが見つかったら、タグ間にテキストを印刷します(含む)。

特定のテキストが見つかったら、タグ間にテキストを印刷します(含む)。

私の使命は、複数の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
  • true(1はブールコンテキストでtrueを意味します)の場合、$flag現在の項目を配列にプッシュします@a
  • が表示されたら、</Directoryブロック操作が完了したことを意味し、ブロックに+ExecCGI文字列が含まれていることを確認して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>

関連情報