
コンテンツが比較的単純で一貫した形式で保持される何百もの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{}'
次に、私は困難に遭遇し、これをシェルスクリプトにする方法を知りませんでした。これにはシェルループが含まれており、成功せずにそれを見つけようと数日を過ごしました。
みんな私を助けてもらえますか?よろしくお願いします!
修正する
それが私がやろうとしていることです。いくつかの問題があります。
- これは1つのデータしか処理できません。
<div class="row">...</div>
これは私が経験した最も困難な問題です(以下に示す問題)。これにはシェルループの問題が含まれます。 - 一度に1つの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
セルを1つずつ抽出しようとするため、テーブルを再構築するのがより困難になります。
使い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
印刷されます。