web-dev-qa-db-ja.com

=〜による文字列パターンマッチング

bash=〜を使用した文字列パターンマッチングを理解するのに問題があります。

私は次の関数を作成しました(心配しないでください-md5sumによるセキュリティアプローチではなく、単に実験的なものです)。

md5 ()  { 
     [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; 
}

いくつかの入力でテストしました。ここでいくつかの参照:

md5sum wp.laenderliste
b1eb0d822e8d841249e3d68eeb3068d3  wp.laenderliste

コントロールサムのソースにファイル名を含む2つの空白が含まれていない場合、比較が不必要に難しくなります。それが観察の起源ですが、その問題を解決する多くの方法よりも興味深いのは私の観察でした。

制御変数を定義し、短すぎるが一致する文字列で関数をテストします。

ok=b1eb0d822e8d841249e3d68eeb3068d3
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done 
fine
fine
fine
fine

これは関数の目的であるため、欠落している "wp.laenderliste"の不一致を無視し、それによってさらに長い不一致を無視することは、期待どおりで問題ありません。

ここで、一致しないランダムなものを追加すると、もちろんエラーが発生し、エラーが発生します。

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done 
baarr
baarr
baarr
baarr

予想通り。しかし、1つだけ、最後に一致しない文字がある場合、何が起こるかを確認します。

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done 
fine
fine
fine
fine

これが私が、これがどのように機能することに気づいていないのか(選択が壊れている)、またはbashのパターンマッチングに実際に1つずれるエラーがあるのですか?

文字列の途中の不一致は、カウント1の問題です。

for i in 5 9 e ; do echo md5 wp.laenderliste ${ok//$i/_} ;done 
md5 wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3
md5 wp.laenderliste b1eb0d822e8d84124_e3d68eeb3068d3
md5 wp.laenderliste b1_b0d822_8d841249_3d68__b3068d3

for i in 5 9 e ; do md5 wp.laenderliste ${ok//$i/_} ;done 
fine
baarr
baarr

Bashバージョン:

bash -version
GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html>

免責事項:md5sumは、意図しない間違いに対してのみ役立ち、攻撃に対しては役立ちません。使用はお勧めしません。

そして、この質問は、より良い解決策や回避策を探すことではありません。それは=〜演算子についてであり、それがそのように振る舞うべきかどうか、そうである場合、その理由です。

5
user unknown

=~)の[[ ]]は、正規表現のパターンマッチです(またはsearch、以下を参照)。これは、ファイル名のワイルドカードと同じパターンを使用する=(または==)とは異なります。

特に、正規表現のアスタリスクは「前のユニットのゼロまたは1つのコピー」を意味するため、abc*abにゼロ以上のcsを加えたものを意味します。

あなたの場合、末尾のアスタリスクは、関数の引数の最後の文字をオプションにします。最後の例では、パターンは...68d3G*になり、G*は空の文字列に一致するため、...68d3のような文字列に一致します。 「任意の文字列」の正規表現は、.*、または「任意の文字、任意の回数」です。

正規表現の一致では、文字列の任意の場所で一致が検索されることに注意してください。whole文字列である必要はありません。したがって、パターンcdeは、文字列abcdefghで見つかります。

あなたはこのようなものを使いたいかもしれません:

[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok

ここでは正規表現の一致は実際には必要ありません。md5sumは末尾のスペース(およびファイル名)を出力するので、パターンでそれを使用して、完全なパターンと一致することを確認できます。そのため、関数に切り捨てられたハッシュを与えると一致しません。

10
ilkkachu

ここでは正規表現を使用せず、文字列の比較のみを行います。

md5 ()  { 
    sum=$(md5sum "$1" | awk '{print $1}')
    [[ $sum = "$2" ]] && echo fine || echo baarr; 
}
0
glenn jackman