grep, sed, awk를 사용하여 html을 필터링하려고 합니다.

grep, sed, awk를 사용하여 html을 필터링하려고 합니다.

저는 cygwin 설치에서 Linux 도구를 사용하는 방법을 스스로 가르치려고 합니다. 나는 쉘 스크립팅의 기초를 스스로 가르치고 동시에 개인 교육도 이수하기 위한 프로젝트를 만들기로 결정했습니다. 나의 초기 프로젝트는 각 우승자를 위해 HTML 페이지를 저장하는 것이었습니다.사하로프상폴더에 넣고 모든 HTML 텍스트 파일을 처리하고 이름, 연도, 출생 및 사망, 출신 국가를 하이픈 형식으로 반환하는 스크립트를 작성합니다. 날짜 형식(1918년 7월 18일 vs. 1938년 1월 23일)에 일부 불일치가 있고 사망 날짜 없이 죽은 사람과 살아있는 사람을 처리할 수 없기 때문에 컴퓨터에 국가를 인식하는 방법을 알려주는 것도 불가능합니다. 수동으로 목록을 작성할 필요 없이 이름을 입력하는 것은 기본적으로 이 프로젝트를 포기한 상태입니다.

이제 HTML 테이블에서 각 수신자의 연도, 이름 및 출신 국가를 반환하려고 합니다.사하로프상위키피디아 페이지.

따라서 다음 예제 HTML이 주어졌습니다.

<tr>
<td>1988</td>
<td><span style="display:none;">Mandela, Nelson</span><span class="vcard"><span class="fn"><a href="/wiki/Nelson_Mandela" title="Nelson Mandela">Nelson Mandela</a></span></span></td>
<td><a href="/wiki/South_Africa" title="South Africa">South Africa</a></td>
<td>Anti-apartheid activist and later President of South Africa</td>
<td><sup id="cite_ref-twentyyears_5-0" class="reference"><a href="#cite_note-twentyyears-5"><span>[</span>5<span>]</span></a></sup></td>
</tr>
<tr>
<td>1988</td>
<td><span style="display:none;">Marchenko, Anatoly</span><span class="vcard"><span class="fn"><a href="/wiki/Anatoly_Marchenko" title="Anatoly Marchenko">Anatoly Marchenko</a></span></span> (posthumously)</td>
<td><a href="/wiki/Soviet_Union" title="Soviet Union">Soviet Union</a></td>
<td>Soviet dissident, author and humans rights activist</td>
<td><sup id="cite_ref-twentyyears_5-1" class="reference"><a href="#cite_note-twentyyears-5"><span>[</span>5<span>]</span></a></sup></td>
</tr>

각 수신자의 연도, 이름, 출신 국가만 반환하는 가장 좋은 방법은 무엇입니까? 이제 나는 /<*>/와 일치하지 않는 모든 것을 반환하는 awk 스크립트를 작성하려고 생각하고 있지만 그것은 내가 원하는 것이 아닙니다. 이름, 연도 및 국가를 구체적으로 선택하는 방법에 대한 조언이나 아이디어를 줄 수 있는 사람이 있습니까? 아니면 내가 스스로 해결할 수 있는 문제보다 더 좋고 관리하기 쉬운 책이 적어도 있습니까? 막상 시작해보니 이 모든 게 터무니없게 들리더군요…

답변1

이미 언급했듯이정규 표현식은 HTML 구문 분석에 적합하지 않습니다.. 다른 것과 비슷하다답변 분석이 작업을 수행하려면 아래와 같은 Ruby 문을 만들 수 있습니다. 필요하다는 점 참고해주세요노코체gem( )으로 설치할 수 있습니다 sudo gem install nokogiri.

ruby -rnokogiri -e 'Nokogiri::HTML(readlines.join).css("tr").each { |tr| tr.xpath(".//td").take(3).each { |td| puts td.content } }' sample.html

지정된 파일(이 경우에는 샘플.html)을 읽고 모든 tr요소를 ​​가져온 다음 td각 요소에 대한 처음 세 요소의 내용을 인쇄합니다.

귀하의 예에서는 다음과 같이 출력됩니다.

1988년
넬슨 만델라 넬슨 만델라
남아프리카
1988년
아나톨리 마르첸코 아나톨리 마르첸코(사후)
소련

문제는 이름이 두 번 포함된 줄입니다. 예를 들어 (읽기 쉽도록 형식화됨)

<td>
  <span style="display:none;">Mandela, Nelson</span>
  <span class="vcard"><span class="fn">
      <a href="/wiki/Nelson_Mandela" title="Nelson Mandela">Nelson Mandela</a>
    </span>
  </span>
</td>

여기서 이름은 spanwith 에서 처음으로 나타나고 style="display:none;"또 다른 에서는 다시 나타납니다 span. 요소 내부에 없는 이름만 추출하는 방법을 잘 모르겠습니다 style="display:none;. (나는 발견했다https://stackoverflow.com/q/6096327/789593그리고https://stackoverflow.com/q/11602077/789593그러나 그들은 올바른 기술을 설명하지 않습니다. 어쩌면 누군가가 해결책을 제안할 수도 있습니다.http://nokogiri.org/Nokogiri/XML/Node.html? )

답변2

여기에서 사용할 수 있는 node.js 패키지를 만들었습니다.곰바. awk와 sed를 대체하는 것과 약간 비슷합니다.

따라서 귀하의 예에서는 다음과 같이 작동합니다.

cat file.html | gumba "stripTags()"

출력:

1988
Mandela, NelsonNelson Mandela
South Africa
Anti-apartheid activist and later President of South Africa
[5]


1988
Marchenko, AnatolyAnatoly Marchenko (posthumously)
Soviet Union
Soviet dissident, author and humans rights activist
[5]

여기서는 oneliner를 사용하지 않고 실제로 당신이 아는 언어로 스크립트를 작성하는 것이 더 낫다고 생각합니다.

답변3

sed -rn '
    /<tr>/ {
        n
        s#<td>([^<]*)</td>#\1#
        h
        n
        s#<td><span[^>]*>([^<]*)</span>.*#\1#
        H
        n
        s#<td><a href=[^>]*>([^<]*)</a>.*#\1#
        H
        x;p
    }
' file

1988
Mandela, Nelson
South Africa
1988
Marchenko, Anatoly
Soviet Union

관련 정보