쉘을 사용하여 HTML을 테이블로 변환하는 방법

쉘을 사용하여 HTML을 테이블로 변환하는 방법

내용이 비교적 단순하고 일관된 형식으로 유지되는 수백 개의 HTML 파일이 있습니다.

이를 테이블로 변환해야 합니다. 이를 위해 쉘 스크립트를 사용할 수 있습니까?

HTML 소스 코드

<html>
<head>
<title>Demo</title>
</head>
<body>
    <h1>Page Title</h1>
    <div class="row">
        <p class="text-1">Text 1</p>
        <p class="text-2">Text 2</p>
        <p class="text-3">Text 3</p>
        <p class="text-4">Text 4</p>
        <p class="text-5">Text 5</p>
        <p class="text-6">Text 6</p>
    </div>
    <div class="row">
        <p class="text-1">Text 1</p>
        <p class="text-2">Text 2</p>
        <p class="text-3">Text 3</p>
        <p class="text-4">Text 4</p>
        <p class="text-5">Text 5</p>
        <p class="text-6">Text 6</p>
    </div>
    <div class="row">
        <p class="text-1">Text 1</p>
        <p class="text-2">Text 2</p>
        <p class="text-3">Text 3</p>
        <p class="text-4">Text 4</p>
        <p class="text-5">Text 5</p>
        <p class="text-6">Text 6</p>
    </div>
</body>
</html>

변환표 소스코드

<table>
    <caption>Page Title</caption>
    <thead>
        <tr>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Text 1</td>
            <td>Text 2</td>
            <td>Text 3</td>
            <td>Text 4</td>
            <td>Text 5</td>
            <td>Text 6</td>
        </tr>
        <tr>
            <td>Text 1</td>
            <td>Text 2</td>
            <td>Text 3</td>
            <td>Text 4</td>
            <td>Text 5</td>
            <td>Text 6</td>
        </tr>
        <tr>
            <td>Text 1</td>
            <td>Text 2</td>
            <td>Text 3</td>
            <td>Text 4</td>
            <td>Text 5</td>
            <td>Text 6</td>
        </tr>
    </tbody>
</table>

이것이 마인드맵입니다.

여기에 이미지 설명을 입력하세요.

질문을 하시기 전, 온라인에서 정보를 찾아보았더니 다음 명령어를 사용하면 HTML 내용을 추출할 수 있다는 것을 알게 되었습니다.강아지도구, 사용법은 다음과 같습니다.

# Extracting page titles
cat demo.html | pup 'body > h1 text{}'

# Extracting paragraph text
cat demo.html | pup 'body > div.row > p.text-1 text{}'
cat demo.html | pup 'body > div.row > p.text-2 text{}'
cat demo.html | pup 'body > div.row > p.text-3 text{}'
cat demo.html | pup 'body > div.row > p.text-4 text{}'
cat demo.html | pup 'body > div.row > p.text-5 text{}'
cat demo.html | pup 'body > div.row > p.text-6 text{}'

다음으로 나는 어려움에 부딪혔고, 이것을 쉘 스크립트로 만드는 방법을 몰랐습니다. 여기에는 쉘 루프가 포함되어 있으며 성공하지 못한 채 이를 알아내려고 며칠을 보냈습니다.

모두 나를 도와줄 수 있나요? 미리 감사드립니다!

고쳐 쓰다

그것이 내가 하려고 하는 일이다. 몇 가지 문제가 있습니다.

  • 이는 하나의 데이터만 처리할 수 있는데 <div class="row">...</div>, 이는 제가 겪은 가장 어려운 문제입니다(아래에 표시된 문제). 여기에는 쉘 루프 문제가 포함됩니다. 여기에 이미지 설명을 입력하세요.
  • 한 번에 하나의 HTML 파일만 변환할 수 있으며 이상적으로는 수백 개의 HTML 파일을 일괄 처리할 수 있습니다(다른 디렉터리로 내보내고 파일 이름을 일관되게 유지하면서 저장).
#!/usr/bin/env bash

# Extracts HTML content
page_title=$(cat demo.html | pup 'body > h1 text{}')
paragraph_text_a=$(cat demo.html | pup 'body > div.row > p.text-1 text{}')
paragraph_text_b=$(cat demo.html | pup 'body > div.row > p.text-2 text{}')
paragraph_text_c=$(cat demo.html | pup 'body > div.row > p.text-3 text{}')
paragraph_text_d=$(cat demo.html | pup 'body > div.row > p.text-4 text{}')
paragraph_text_e=$(cat demo.html | pup 'body > div.row > p.text-5 text{}')
paragraph_text_f=$(cat demo.html | pup 'body > div.row > p.text-6 text{}')

# Print the contents in a predetermined format
cat << EOF
<table>
    <caption>$page_title</caption>
    <thead>
        <tr>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>$paragraph_text_a</td>
            <td>$paragraph_text_b</td>
            <td>$paragraph_text_c</td>
            <td>$paragraph_text_d</td>
            <td>$paragraph_text_e</td>
            <td>$paragraph_text_f</td>
        </tr>
    </tbody>
</table>
EOF

답변1

다음은 어느 정도 트릭을 수행해야 합니다. 저를 기억하십시오.

  • 테스트 없이 그냥 작성했습니다.편집: 이제 테스트하고 몇 가지 버그를 수정했으므로 제대로 작동하는 것 같습니다.
  • 나는 극단적인 경우(다중 <h1>, <tbody>테이블 필드 내 등...)를 무시합니다.

"scriptname.pl"에 넣고 2번째와 3번째 줄의 파일 이름을 변경한 후 실행하세요.perl scriptname.pl

#!/usr/bin/perl
open my $ifh, "inputfilename.html";
open my $ofh, ">outputfilename.html";
while(<$ifh>) {
  if(/<h1>(.*)<\/h1>/) {
    my $header = << "END";
  <table>
    <caption>$1</caption>
    <thead>
        <tr>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
            <th>Hard Code</th>
        </tr>
    </thead>
    <tbody>
END
    print $ofh $header;
  } elsif(/<div class="row">/) {
    print $ofh "<tr>\n";
  } elsif(/<\/div>/) {
    print $ofh "</tr>\n";
  } elsif(/<p class=".*?">(.*)<\/p>/) {
    print $ofh "<td>$1</td>\n";
  } elsif(/<\/body>/) {
    print $ofh "</tbody>\n</table>\n</body>\n";
  } else {
    print $ofh $_;
  }
}
close $ofh;
close $ifh;

답변2

셀을 하나씩 추출하려고 하므로 테이블을 다시 작성하기가 더 어려워집니다.

사용이 간편 bash하며 다음과 pup같은 사항만 적용됩니다.

#!/bin/bash

count=$(grep '<div ' demo.html | wc -l)
page_title=$(cat demo.html | pup 'body h1 text{}')

tbody() {
    for ((i=1;i<count+1;++i)); do
        IFS=, row=$(cat demo.html | pup "body div.row:nth-of-type($i) text{}" | grep '\S' | paste -s -d, -)
        printf "\t\t<tr>\n"
        printf '\t\t\t<td>%s</td>\n' $row
        printf "\t\t</tr>\n"
    done
}

cat <<EOF
<table>
    <caption>$page_title</caption>
    <thead>
        <tr>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
        </tr>
    </thead>
    <tbody>
`tbody`
    </tbody>
</table>
EOF

산출

<table>
    <caption>Page Title</caption>
    <thead>
        <tr>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
            <th>Hard Coded</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Text 1</td>
            <td>Text 2</td>
            <td>Text 3</td>
            <td>Text 4</td>
            <td>Text 5</td>
            <td>Text 6</td>
        </tr>
        <tr>
            <td>Text 1</td>
            <td>Text 2</td>
            <td>Text 3</td>
            <td>Text 4</td>
            <td>Text 5</td>
            <td>Text 6</td>
        </tr>
        <tr>
            <td>Text 1</td>
            <td>Text 2</td>
            <td>Text 3</td>
            <td>Text 4</td>
            <td>Text 5</td>
            <td>Text 6</td>
        </tr>
    </tbody>
</table>

설명하다

아이디어는 마지막 행까지 반복하여 행별로 데이터를 추출하는 것입니다. 이 코드 조각은 행 수를 제공합니다.

grep '<div ' demo.html | wc -l

그런 다음 이를 선택기로 사용하면 nth-of-type(n)열 대신 전체 행을 가져올 수 있습니다. grep '\S'빈 줄을 제거 하려면 이를 전달해야 합니다 . 그런 다음 에 전달하면 paste -s -d, -쉼표로 구분된 결과가 생성됩니다.

IFS=, row=$(cat demo.html | pup "body div.row:nth-of-type($i) text{}" | grep '\S' | paste -s -d, -)

각 매개변수 printf '\t\t\t<td>%s</td>\n' $row로 확장되어 다음과 같이 래핑 됩니다 .printf '\t\t\t<td>%s</td>\n' 'Text 1' 'Text 2' ...<td>...</td>

해당 섹션을 완전히 제거하면 들여 \t쓰기된 결과만 인쇄됩니다.

관련 정보