大きな行文字列の開始と終了の一致に基づいてhtmlエンティティに依存せずにフィルタリングし、長さに関係なくパターン間にテキストを保持します。

大きな行文字列の開始と終了の一致に基づいてhtmlエンティティに依存せずにフィルタリングし、長さに関係なくパターン間にテキストを保持します。

次のような1行のファイルがあります。パスツールビンしかし、はるかに長いです。


私の目標は、example1:start with <aend with </a>
example2:start with PZend withの文字列部分のみをフィルタリングすることですs16
。したがって、各場合、テキストはHTMLエンティティに依存せず、一致の間に保持されます。

FreeBSDHTMLエンティティに依存する解決策はすでにあります。

  1. 複数行で美しく飾るtidy -i -m -w 160 -ashtml -utf8 ~/file
  2. 文字列が含まれていない場合は行を削除するsed -i '' '/\<\/a\>/!d' ~/file

ところで、HTMLエンティティに依存せずに直接フィルタを実行しようとしています。現時点では、一致の正確な先頭のみを取得できますが、フィルタリングしている文字列の内容がどれほど長いかわからないため、一致の終わりを正確に取得することはできません。予期しない結果の再現手順をご覧ください。

予期しない結果を再現する手順

wget -O ~/file https://pastebin.com/raw/xbti369J
grep -E -o ".{0,0}PZ.{0,46}" ~/file

結果

固定長を要求したため、行が正しくありません。
PZ</td><td class="s15">€ 1.20</td><td class="s16
PZ</td><td class="s15"></td><td class="s16">A</t
目的は、長さに関係なく、次のように結果的な線パターンを得ることです。
PZ</td><td class="s15">€ 1.20</td><td class="s16
PZ</td><td class="s15"></td><td class="s16

答え1

のようなXMLパーサーを使いたいですxmllint

a次のXPath式を使用して要素間のテキストをフィルタリングします。

xmllint --html --xpath '//a/text()' <file>

答え2

PZaから最も近いものまですべての部分を選択するには、s16貪欲ではない一致が必要です。これは(拡張)正規表現ではサポートされていませんが、grepGNUにはgrepPerlスタイルの式のerlオプションがあります。-P

grep -P -o "PZ.*?s16" ~/file

Perl 式 ".*?" は、式全体を一致させる文字のうち最も短い一致を表します。

PZ試合の中に多くがあるので、これはまだあなたが望むものではないかもしれませんが、あなたの例を理解すると後ろにあるものだけがPZ必要であり、s16その間には何も必要ありません。PZそれでは、2番目のステップで不要なアイテムを削除してみましょう。

grep -P -o "PZ.*?s16" ~/file | sed 's/.*PZ/PZ/'

答え3

これを行う方法はいくつかあります。

1PCREが有効なGNU grep。ここでは、貪欲ではない正規表現*?を負の予測と組み合わせて使用​​して、PZとs16の間に発生するすべてのPZを削除します。

grep -Po 'PZ(?:(?!PZ).)*?s16' file

2 そのようなgrepバージョンにアクセスできない場合は、正規表現をサポートする元のバージョンであるPerlを使用できます。

perl -lne 'print for /PZ(?:(?!PZ).)*?s16/g' file

サム これにはsedを使用できます。第1段階では、PZ及びs16をBOL及びEOLとして示す。この修正された入力は、PZで始まりs16で終わる行を選択する2番目のsedに渡され、内部的にPZを含めないでください。

< file \
sed 's/PZ/\n&/g;s/s16/&\n/g' |
sed '/^PZ.*s16$/!d;/..*PZ/d' |
cat

4 私たちを。ここでは1つのsed呼び出しのみが使用されます。 GNU sedが必要です。

sed '/\n/{
  /^PZ[^\n]*s16/!D
  s//&\n/;P;D;}
  s/PZ/\n&/g;D
' file

関連情報