私はシェルスクリプトの初心者です。curl を使って http リクエストを送信し、正規表現を使っていくつかの文字列を抽出したいと考えています。例えば、httpのレスポンスからドメイン名を抽出するにはどうすればよいでしょうか?(例は学習目的のみです)
#!/bin/bash
name=$(curl google.com | grep "www\..*com")
echo "domain name is"
echo $name
bashの正規表現]1を使う。
re="http://([^/]+)/"
if [[ $name =~ $re ]]; then echo ${BASH_REMATCH[1]}; fi
編集 - OPから構文の説明を求められました。 正規表現の構文は大きなテーマなので、ここで完全に説明することはできませんが、例題を理解するのに十分な説明を試みます。
re="http://([^/]+)/"
これは、bashの変数re
に格納されている正規表現です。つまり、入力文字列をマッチさせて、できれば部分文字列を抽出したいということです。 それを分解すると
[]
通常、角括弧は "括弧内の任意の文字にマッチする"という意味で使用されます。 つまり、c[ao]t
は、"cat"と"cot"の両方にマッチします。 []の中の
^文字は、これを修正して、"角括弧内の文字を*除く*任意の文字にマッチするようにします。 つまり、この場合、
[^/]`は、"/"を除くすべての文字にマッチします。+
をつけると、"直前の部分式の1つ以上にマッチする"となります。 つまり、[^/]+
は、"/"を除くすべての文字の集合の1つ以上にマッチします。()
の括弧をつけると、その副式にマッチしたものを後の処理のために保存したいということになります。 使用している言語がこれをサポートしていれば、これらのサブマッチを取得するためのメカニズムが提供されます。 bashの場合は、BASH_REMATCH配列です。次に、入力された文字列が正規表現にマッチするかどうかをテストする必要があります。 これにはbashの条件式が使えます。
if [[ $name =~ $re ]]; then
echo ${BASH_REMATCH[1]}
fi
bashでは、[[ ]]
は拡張された条件付きテストを指定し、=~
bash正規表現演算子を含むことができます。 この例では、入力文字列 $name
が正規表現 $re
にマッチするかどうかをテストします。 一致した場合、正規表現の構造上、サブマッチがあることが保証されているので(括弧 ()
から)、BASH_REMATCH 配列を使用してそれにアクセスできます。
要素はこれらに順に対応します。 この場合、
${BASH_REMATCH1}`には"www.google.com"が含まれ、これがあなたの求める文字列だと思います。BASH_REMATCH 配列の内容は、正規表現の =~
演算子が最後に使用されたときにのみ適用されることに注意してください。 したがって、さらに正規表現のマッチを行う場合は、毎回この配列から必要な内容を保存する必要があります。
これは長い説明のように見えるかもしれませんが、私は正規表現の複雑な部分をいくつか説明しました。 正規表現は非常に強力で、性能もそれなりにあると思いますが、正規表現の構文は複雑です。 また、正規表現の実装は様々なので、言語によってサポートする機能が異なり、構文にも微妙な違いがあるかもしれません。 特に、正規表現内の文字のエスケープは、その文字が特定の言語で異なる意味を持つ場合には、厄介な問題となります。
なお、$re
変数を別の行に設定して、条件の中でこの変数を参照する代わりに、正規表現を直接条件の中に入れることができます。 しかし、bash 3.2では、このようなリテラルな正規表現を引用符で囲むことが必要かどうかについて、ルールが変更されました。 正規表現を別の変数に入れることは、これを回避するための簡単な方法で、=~
マッチ演算子をサポートするすべてのbashのバージョンで、条件が期待通りに動作するようになります。
一つの方法は、sed
を使うことです。 例えば、以下のようになります。
echo $name | sed -e 's?http://www\.??'
通常、sed
の正規表現は、`/'で区切られていますが、'/'を検索しているので、 '?'を使うことができます。 これもbashのトリックです。DigitalTraumaさんの回答を見て、これを提案すべきだと思いました。 似たようなものですね。
echo ${name#http://www.}
(DigitalTraumaは、"http://"を処理する必要があることを私に思い出させてくれた功績もあります)。