web-dev-qa-db-ja.com

sed:URLクエリ文字列のキーと値のペアの値を抽出する

Sedを使用して、URLのクエリ文字列にある多くのキーと値のペアの1つの値の部分を抽出しようとしています

これは私が試していることです:

_echo 'http://www.youtube.com/watch?v=abc&g=xyz' | sed 's@^https?://(www.)?youtube.com/(watch\\?)?.*?v(=|/)([a-zA-Z0-9\-_]*)(&.*)?$@$4@'
_

ただし、常に入力URLをそのまま出力します。

何が悪いのですか?

更新1

いくつかの問題を明確にするために:

  1. 入力の有効性をチェックし、入力が有効な場合にのみ出力を生成しようとしているため、正規表現は必要以上に複雑です。したがって、より厳密な一致です。
  2. 必要な出力は、クエリ文字列のキー「v」の値です。
  3. 使用しているsedのバージョンを見つけることができませんでしたが、Mac OS X(10.7.5)に付属しているバージョンです。
  4. 私のバージョンのsed $ 1、$ 2などは一致するようですが、\ 1、\ 2などはエラーを出します:sed: 1: "s@^https?://(www.)?yout ...": \4 not defined in the RE- 不正解です!後でわかりました。混乱を招きましたことをお詫び申し上げます。

更新2

以下の@slhckの提案に基づいてsed REをより具体的にするために更新しましたが、問題は以前と同じままです。

更新

このバージョンのmansedページに基づいて、これはBSD風味のバージョンであると思われます。

6
markvgti

abcだけが必要な場合はさらに簡単です:

 echo 'http://www.youtube.com/watch?v=abc&g=xyz' | awk -F'[=&]' '{print $2}'

xyzが必要な場合:

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | awk -F'[=&]' '{print $4}'

説明:

  • awk:入力ファイルを1行ずつ自動的に処理し、各行をフィールドに分割するスクリプト言語です。したがって、awkを使用してファイルを処理する場合、各行の最初のフィールドは$1、2番目のフィールドは$2など、$Nまでです。デフォルトでは、awkはフィールド区切り文字として空白を使用します。

  • -F'[=&]'-Fは、フィールド区切り文字をスペースから別のものに変更するために使用されます。この場合、私はそれに class の文字を与えています。大括弧([ ])は、多くの言語で文字のグループを示すために使用されます。したがって、具体的には、-F'[=&]'は、awk&=の両方をフィールド区切り文字として使用する必要があることを意味します。

  • したがって、&=を区切り文字として使用して、質問からの入力文字列を指定すると、awkは次のフィールドを読み取ります:

    http://www.youtube.com/watch?v=abc&g=xyz
    |----------- $1 -------------| --- - ---      
                                    |  |  |
                                    |  |  ̣----- $4
                                    |  -------- $3
                                    ----------- $2
    

    だから、あなたがしなければならないすべてはあなたが望むものを印刷することです{print $4}


また、文字列が有効なYouTube URLであることを確認する必要があると言いましたが、sedを使用してそれを行うことはできません。単に行全体を印刷します。 Perlのようなツールを使用して、正規表現が一致する場合にのみ印刷することができます:

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | 
  Perl -ne 's/http.*www.youtube.com\/watch\?v=(.+?)&.+/$1/ && print'

最後に、単純にabcを印刷するには、標準のUNIXツールを使用できます cut

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | 
  cut -d '=' -f 2 | cut -d '&' -f 1
12
terdon

「xyz」が必要な場合は、これを試してください(GNU sed):

echo 'http://www.youtube.com/watch?v=abc&g=xyz' | sed 's/.*=\([[:alnum:]]*\).*/\1/'
2
Endoro

@Endoroと@slhckによって与えられた回答に基づいてsedを試してみると、最終的な回答(私が欲しかったもの)に私を導きました。これは、Mac OS X(10.7.5)上のsedのバージョンで私にとってうまくいくものです:

_echo 'http://www.youtube.com/watch?v=dnCkNz_xrpg' | sed -E 's@https?://(www\.)?youtube.com/(watch\?).*v=([-_a-zA-Z0-9]*).*@\3@'
_

説明:

  1. _-E_はsedに拡張REを使用させるためのものです。 sedの他のバージョンでは、_-r_が同等のオプションになる場合があります。
  2. REよりも複雑そうに見えるREは、これが有効なYouTubeリンクであることも確認することです。このREの最初の部分を必要に応じて変更します(例:https?://(www\.)?example.com/(.*\?).*key=([^&]*).*
  3. _\3_は、括弧内の3番目の式に一致し、それを回答/一致として出力します(これは私が望んでいることです)。
  4. 通常の 's ///'の代わりに 's @@@'を使用して、URL内の多くのスラッシュ(_\_)をエスケープする必要がないようにします。

私が助けられたことで、これが他の人にも役立つことを願っています。

2
markvgti

本当に動画IDだけが必要な場合– v=と次の&の間のすべて–使用するだけです。

sed -r 's/.*v=([[:alnum:]]*).*/\1/'

あなたのコマンドのどこが悪いのですか?

  • 拡張正規表現を使用するには、-rが必要です。省略した場合、sedは括弧を文字どおりに解釈するため、一致グループはありません。 BSD sedでは、代わりに-Eオプションを使用してください。

  • 一致を参照するには$1を使用しますが、\1を使用する必要があります。 $1は、実際には、たとえば現在のスクリプトに渡されるシェル引数です。

  • パラメータ値と一致させるには、[[:alnum:]](またはIDの設定方法によっては[a-zA-Z0-9_])などの文字クラスを使用する必要があります。そうしないと、次の&もキャプチャされます。正規表現は貪欲であり、abc&g=xyzを使用する場合は.*?に一致します。遅延定量化はBRE/EREではサポートされておらず、Perl正規表現またはその他の「モダン」フレーバーでのみサポートされているためです。

1
slhck

SEDが一致しないため、常にURLが表示されます。

    echo 'http://www.youtube.com/watch?v=abc&g=xyz' | sed 's!^http://www.youtube.com/watch\?\(.*=.*\)&\(.*=.*\)!\1!'

V = abcを表示します

0
PraveenMak