ダウンロードしたWebページで文字列を見つけようとしますcurl
。私はgrep
一致する文字列を見つけるために使用します。正規表現柄。
以下は私が見つけたい文字列です。
./download/file.php?id=86753
この文字列は部分Webページのより大きな文字列は次のとおりです。
href="./download/file.php?id=86753"
私が使用するマントラgrep
は次のとおりです。
grep -Eo '\.\/download\/file\.php\?id=[0-9]+' dlfile.html
しかし、見つかりました。何もないhtmlファイルから。ただしgrep
、次のように変更すると、2つの一致が生成されます。これ最初のゲーム2つ目は役に立たない障害物なので、含めないでください。
grep -Eo '\/download\/file\.php\?id=[0-9]+' dlfile.html
/download/file.php?id=86753
/download/file.php?id=62517
2番目の(不要な)一致を含む文字列は次のとおりです。
href="https://web.archive.org/web/20190824162104/https://www.somewhere.com/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32"
.
問題は、文字列の先行(ドット)が認識されないようです。これは、必要な文字列と望ましくない文字列の主な違いです。
Q:これがうまくいかないのはなぜですか?何が必要ですか?
私の環境:Debian派生バージョン(Raspberry Pi)、「bullseye」バージョン
私はどちらを使用していますかgrep
?bash
$ grep --version
grep (GNU grep) 3.6
...
$ bash --version
GNU bash, version 5.1.4(1)-release (arm-unknown-linux-gnueabihf)
答え1
grep -E
ERE(拡張正規表現)が必要です。ドットは常にリテラルにエスケープする必要があります。疑問符は ERE に有効な演算子なので、リテラルと一致させるにはエスケープする必要があります。
echo 'href="./download/file.php?id=86753"' |
grep -Eo '\./download/file.php\?id=[0-9]+'
頼む、
grepが先行する「.」を無視するのはなぜですか?
問題は、文字列の前の.(ドット)を認識しないようです。
あなたのパターンは一致し、リテラルポイントが必要です(これは正しい\.
意味です)。ただし、質問に記載されている文字列は検索しようとしているWebページには表示されません。grep
これを無視しないでください。望むより:
xmlstarlet format --html BDegguyM 2>/dev/null |
xmlstarlet select -T -t -v '//a[@class="postlink"]/@href' -n
https://forums.raspberrypi.com/download/file.php?id=86753
https://web.archive.org/web/20190824162104/https://www.raspberrypi.org/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32
私はあなたがこれらの最初のものが欲しいと仮定しているので、それを抽出してみましょう。
xmlstarlet format --html BDegguyM 2>/dev/null |
xmlstarlet select -T -t -v '//dl[@class="file"]//a[@class="postlink"]/@href' -n
https://forums.raspberrypi.com/download/file.php?id=86753
次から始まる/download
部分だけが欲しいなら
xmlstarlet format --html BDegguyM 2>/dev/null |
xmlstarlet select -T -t -v '//dl[@class="file"]//a[@class="postlink"]/@href' -n |
sed -E 's!^https?://[^/]+!!'
/download/file.php?id=86753
grep
操作に適したツールの代わりに実際に使用したい場合は、同じ結果が返されます。
grep -Po 'https?://[^/]+\K/download/file.php\?id=\d+' BDegguyM
/download/file.php?id=86753
答え2
タイトル行の質問に対する回答:
grepが先行する「.」を無視するのはなぜですか?
簡単に言えば、そうではありません。
1つのファイルに付属の2つのサンプル入力行を使用します。
$ cat dlfile.html
href="./download/file.php?id=86753"
href="https://web.archive.org/web/20190824162104/https://www.somewhere.com/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32"
■前の不要な(おそらく無害であるがPOSIXに従って定義されていない動作に確実に依存する)バックスラッシュを削除し、質問から/
2つのコマンドを実行します。grep
$ grep -Eo '\./download/file\.php\?id=[0-9]+' dlfile.html
./download/file.php?id=86753
$ grep -Eo '/download/file\.php\?id=[0-9]+' dlfile.html
/download/file.php?id=86753
/download/file.php?id=62517
最初のものはgrep
先行を含み、先行する入力の文字列.
とのみ一致し.
、2番目はgrep
先行を含まず、.
当然aで始まらない入力の2つの文字列と一致します.
。
grep
上記の最初の事項についてのあなたのコメントに関して:
しかし、これはhtmlファイルに何も見つかりません。
それから:
- 質問のgrepコマンドが実際に使用するコマンドとは異なります。
- 実際のHTMLファイルには、サンプル入力として使用するために提供した文字列は含まれていません。
したがって、コマンドがどのような形であるか、入力がどのような形であるかわからない場合は、一部の入力を解析するコマンドをデバッグするのに役立つために実際にできることはありません。
答え3
ここにはすでに多くのコメントがありました。それらのいくつかは正当な懸念と質問を提起しました。ついに問題が解決したと思い、仕上げのためにここに投稿します。
あなたが収集したように、私は必要な情報項目を含む文字列のURLを「スクレイピング」しています。約2年前、私はこの作業を「自動化」するスクリプトを開発しましたが、それはうまくいきました。このスクリプトは主に次の2つのことを行います。
curl
&grep
ウェブページ- 結果に応じて別の
grep
措置を講じてください。
「何か変わった」数日前。私の「信頼できる」スクリプトは、実行されるたびにエラーが発生し始めました。このエラーは、grep
文字列が見つからないことを示します。私がgrep
使用するもの:
curl blah-blah | grep -o '\.\/download\/file\.php?id.[0-9]*'
今日まで、私は何も変わったことがないことを知りません。変更の1つは、サイトが「CloudFlare」という会社にアウトソーシングされたことです。もう1つは、curl
ブラウザのダウンロードを処理するのと同じ方法でダウンロードを処理しないようです。もう一つの変化が起きているようです。
私の質問に反映された混乱は、部分的にこれらのサイトの変更によるものです。しかし、それはほとんど私のせいです。。質問を投稿する前に、もっと忍耐力を持って、エラーをより徹底的に調査する必要がありました。関係者全員にお詫び申し上げます。
私がこの経験を通して学んだと主張する一つのことは次のとおりです。grep
HTMLを解析するのに適したツールではありません。。共有する参考資料が2つあります。
これ物議を醸すワイヤーSOでHTMLを解析するための正規表現の再利用
これHiks Gerganovの情報投稿タイトルは、「シェルのHTMLタグ間でテキストを抽出するためのHTML解析」です。
答え4
\/
一般に変更すると正常に動作します/
。
#!/usr/bin/sh
printf 'href="%s"\n' \
'./download/file.php?id=86753' \
'elsewhere/download/file.php?id=86753' |
grep -oE '\./download/file\.php\?id=[0-9]+'
出力:
./download/file.php?id=86753
望ましくないギリギリな状況をよりよく拒否するために、\B
始めと終わりに追加することを検討することもできます。\b