특정 텍스트가 발견되면 태그 사이에 텍스트를 인쇄합니다(포함).

특정 텍스트가 발견되면 태그 사이에 텍스트를 인쇄합니다(포함).

내 임무는 여러 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>

관련 정보