한 번에 라인 일치 및 콘텐츠 추출

한 번에 라인 일치 및 콘텐츠 추출

태그가 있는 행을 찾고 태그 사이의 내용을 가져오고 h2싶습니다 .p

<main>Nothing</main>
<h2>Hello</h2><p>World</p>
<h2>Bells</h2><p>Walls</p>
<h2>Jelly</h2><p>Minus</p>
<p>Fluff</p>

...탭으로 구분된 목록으로:

Hello World
Bells Walls
Jelly Minus

나는 현재 다음을 사용합니다:

grep -E "<h2>(.*)<\/h2><p>(.*)<\/p>" | sed -E "s/<h2>(.*)<\/h2><p>(.*)<\/p>/\1 \2/"

grep <pattern>다만, 먼저 해야 한다는 게 좀 귀찮은 것 같아요 sed <the same pattern>. 한 번만 모드를 사용하여 단일 유틸리티로 이 작업을 수행할 수 있습니까?

답변1

XML 파서를 사용하는 것은 정말 좋은 생각이지만 어떤 이유로 파서를 사용할 수 없는 경우(파일 형식이 올바르지 않거나 파서가 설치되어 있지 않은 등) PERL을 사용할 수 있습니다. 이 목적을 위해:

$ perl -ne 'if(/<h2>(.*?)<\/h2><p>(.*?)<\/p>/){print "$1\t$2\n"}' filename.ext
Hello   World
Bells   Walls
Jelly   Minus

나는 예상치 못한 결과가 나오지 않도록 지연 일치를 사용하는 것을 선호합니다.

테스트.txt

<h1>Nothing</h1>
<h2>Hello</h2><p>World</p><h2>Goodbye</h2><p>Earth</p>
<h2>Bells</h2><p>Walls</p>
<h2>Jelly</h2><p>Minus</p>
<h3>Zip</h3>

$ perl -ne 'if(/<h2>(.*?)<\/h2><p>(.*?)<\/p>/){print "$1\t$2\n"}' test.txt
Hello   World
Bells   Walls
Jelly   Minus
$ perl -ne 'if(/<h2>(.*)<\/h2><p>(.*)<\/p>/){print "$1\t$2\n"}' test.txt
Hello</h2><p>World</p><h2>Goodbye       Earth
Bells   Walls
Jelly   Minus

보시다시피 정규식만으로는 도메인별 도구로 얻을 수 있는 모든 것을 얻을 수 없습니다. 괜찮다면 괜찮습니다. 입력이 패턴과 정확히 일치하지 않으면 부정확한 결과가 나올 수도 있다는 점을 기억하세요!

답변2

올바른 방법은 다음과 같이 하는 것입니다.xmlstarlet도구(xml/html 데이터 구문 분석용):

xmlstarlet sel -t -m '//h2' -v 'concat(., "'$'\t''", ./following-sibling::p)' -n file

산출:

Hello   World
Bells   Walls
Jelly   Minus

답변3

인용되지 않은 정규식을 포함하기 위해 사용하는 정규식의 경우 ()정규식 구문을 확장해야 합니다(또는 각각 ()\(및 로 바꿔야 합니다 \)). 이것은 매우 간단합니다.

[^<]또한 포인트 대신 욕심 많은 매치를 너무 많이 사용하는 것을 피할 수도 있습니다 .

물론 변수를 설정하고 따옴표를 사용하여 수행할 수 있습니다.오직sed:

$ a='<h2>([^<]*)<\/h2><p>([^<]*)<\/p>'                                                                    
$ sed -nE '/'"$a"'/s/'"$a"'/\1 \2/p' infile

그러나 이것이 단순화될 수 있기 때문에 더 좋아집니다. Sed는 마지막으로 사용된 정규식을 기억하므로 왼쪽 s//(비어 있음)이면 충분합니다.

$ sed -nE '/'"$a"'/s//\1 \2/p' infile

또는 변수 없이:

$ sed -nE '/<h2>([^<]*)<\/h2><p>([^<]*)<\/p>/s//\1 \2/p' infile
Hello World
Bells Walls
Jelly Minus

답변4

가능한 해결 방법은 다음과 같습니다 sed.

sed 's/<[^13>]*>/ /g' test | sed 's/<h[13]>.*<\/h[13]>//' <file>

 Hello  World
 Bells  Walls
 Jelly  Minus

둘째, 불필요한 태그 sed를 제거하세요 .<h1><h3>

패턴 설명:

/<[^13>]*>/ /- 임의의 기호로 *시작 <하고 끝나는 텍스트를 검색합니다 >. 그러나 라벨 사이의 기호 1또는3 기필코 아니다( ^) 참석하다.

관련 정보