一度にラインマッチングとコンテンツ抽出

一度にラインマッチングとコンテンツ抽出

タグ付きの行を見つけ、タグ間の内容を取得したいと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 必然ではない^)出席する。

関連情報