내용이 비교적 단순하고 일관된 형식으로 유지되는 수백 개의 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
쓰기된 결과만 인쇄됩니다.