program tip

grep, regex 또는 perl을 사용하여 패턴에 따라 문자열을 추출하는 방법

radiobox 2020. 10. 14. 07:41
반응형

grep, regex 또는 perl을 사용하여 패턴에 따라 문자열을 추출하는 방법


다음과 같은 파일이 있습니다.

<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>

나는 따라 따옴표 안에 아무것도 추출해야 name=즉,, content_analyzer, content_analyzer2content_analyzer_items.

Linux 상자에서이 작업을 수행하고 있으므로 sed, perl, grep 또는 bash를 사용하는 솔루션이 좋습니다.


결과에 포함하지 않고 콘텐츠를 일치시켜야하므로 (일치해야 name="하지만 원하는 결과의 일부가 아님) 어떤 형태의 제로 너비 일치 또는 그룹 캡처가 필요합니다. 다음 도구를 사용하여 쉽게 수행 할 수 있습니다.

Perl

Perl을 사용하면 n옵션을 사용하여 한 줄씩 반복하고 일치하는 경우 캡처 그룹의 내용을 인쇄 할 수 있습니다 .

perl -ne 'print "$1\n" if /name="(.*?)"/' filename

GNU grep

GNU grep과 같은 향상된 버전의 grep이있는 경우 -P옵션을 사용할 수 있습니다. 이 옵션은 Perl과 유사한 정규식을 활성화 \K하여 단축형 lookbehind 를 사용할 수 있습니다 . 일치 위치를 재설정하므로 너비가 0이됩니다.

grep -Po 'name="\K.*?(?=")' filename

o옵션은 grep이 전체 행 대신 일치하는 텍스트 만 인쇄하도록합니다.

Vim-텍스트 편집기

또 다른 방법은 텍스트 편집기를 직접 사용하는 것입니다. Vim을 사용하면이를 수행하는 다양한 방법 중 하나는 줄없이 줄을 삭제 name=한 다음 결과 줄에서 내용을 추출하는 것입니다.

:v/.*name="\v([^"]+).*/d|%s//\1

표준 grep

이러한 도구에 액세스 할 수없는 경우 어떤 이유로 표준 grep으로 비슷한 작업을 수행 할 수 있습니다. 그러나 주변을 둘러 보지 않으면 나중에 정리가 필요합니다.

grep -o 'name="[^"]*"' filename

결과 저장에 대한 참고 사항

위의 모든 명령에서 결과는로 전송됩니다 stdout. 다음을 추가하여 파일에 파이핑하여 언제든지 저장할 수 있음을 기억하는 것이 중요합니다.

> result

명령의 끝까지.


정규식은 다음과 같습니다.

.+name="([^"]+)"

그런 다음 그룹화는 \ 1


Perl을 사용하는 경우 XML :: Simple , XML :: Twig 또는 XML :: LibXML 을 구문 분석하는 모듈을 다운로드합니다 . 바퀴를 재발 명하지 마십시오.


이 목적을 위해서는 정규식보다는 HTML 파서를 사용해야합니다. 다음을 사용하는 Perl 프로그램 HTML::TreeBuilder:

프로그램

#!/usr/bin/env perl

use strict;
use warnings;

use HTML::TreeBuilder;

my $tree = HTML::TreeBuilder->new_from_file( \*DATA );
my @elements = $tree->look_down(
    sub { defined $_[0]->attr('name') }
);

for (@elements) {
    print $_->attr('name'), "\n";
}

__DATA__
<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>

산출

content_analyzer
content_analyzer2
content_analyzer_items

이것은 그것을 할 수 있습니다 :

perl -ne 'if(m/name="(.*?)"/){ print $1 . "\n"; }'

다음은 HTML tidy 및 xmlstarlet을 사용하는 솔루션입니다.

htmlstr='
<table name="content_analyzer" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
<type="global" />
</table>
'

echo "$htmlstr" | tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
sed '/type="global"/d' |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

죄송합니다. sed 명령은 물론 tidy 명령 앞에 와야합니다.

echo "$htmlstr" | 
sed '/type="global"/d' |
tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

If the structure of your xml (or text in general) is fixed, the easiest way is using cut. For your specific case:

echo '<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>' | grep name= | cut -f2 -d '"'

참고URL : https://stackoverflow.com/questions/5080988/how-to-extract-string-following-a-pattern-with-grep-regex-or-perl

반응형