私は以下の正規表現を持っています (<th>Password</th>s*<td>)w*(</td>)
一致する <th>Password</th><td>root</td>
このHTMLでは:
<tr>
<th>Password</th>
<td>root</td>
</tr>
しかし、このTerminalコマンドは一致を見つけられません:
perl -pi -w -e "s/(<th>Password</th>s*<td>)w*(</td>)/$1NEWPASSWORD$2/g" file.html
それは、間の空白と関係があるようです。 </th>
そして <td>
しかし </th>s*<td>
RegExで動作しますが、なぜPerlで動作しませんか。
代用してみた s*
ために n*
, r*
, t*
そしてそれらのさまざまな組み合わせが、まだ一致しません。
実用的な例が見られます ここに.
どんな助けでも感謝しています。
回答:
回答№1の場合は3置換は、一度にファイルの1行にのみ適用されます。
ファイル全体を一度に読み込むことができます。 -0
このようなオプション
perl -w -0777 -pi -e "s/(<th>Password</th>s*<td>)w*(</td>)/$1NEWPASSWORD$2/g" file.html
それは 遠い 以下のような適切なHTMLパーサを使用することをお勧めします。 HTML::TreeBuilder::XPath
このようにデータを処理するには、正規表現を使用して特定のHTML構造のすべての可能な表現を説明することは非常に困難です。
回答№2については2
Perlはファイルを一度に1行ずつ評価します。たとえば、2行に渡って一致させようとしているので、perlは最初の行で探している文字列の終わりを見つけず、2番目の行で探している行の先頭を見つけません。
ファイルをフラット化することもできます。一時的に1行にHTML(ファイルのサイズやパフォーマンスがそれほど重要ではない場合にも有効です)または見つけた行を追跡するためにもっと洗練されたロジックを記述する必要があります。
"multiline regex perl"を検索してみてください。
答え№3の2
これを行うためにsedを使うことができます:
sed -i "/<th>Password</th>/{n;s!<td>[^<]*!<td>NEWPASSWORD!}" file.html
別のsedのバージョン:
sed -i "/<th>Password</th>/!b;n;s/<td>[^<]*/<td>NEWPASSWORD/" file.html