テストを使用して正規表現を否定する方法

テストを使用して正規表現を否定する方法

これは文法的に間違っています:

#!/usr/bin/env bash

dimension="4x5"

if [[ "$dimension" !=~ '[0-9]x[0-9]' ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 return 1;
fi

上記は構文が悪いです...だから私の質問は - これを行う方法はありますか?!=~

...だと思います!~。もしそれが本当なら、否定ルールなんてそんなものでしょう。わかりました、テストしてみましたが、!~これも機能しません。

答え1

!=~キーワードにはor!~演算子はありません[[。代わりに、比較の結果を否定します。

[[ ! "string" =~ regex ]]

議論の引用に関してregex、マニュアルには次のように記載されています。

パターンの任意の部分を引用符で囲むと、引用符で囲んだ部分が文字列として一致するように強制できます。

regexしたがって、シェル オプションcompat31が設定されていない限り、正規表現部分は引用符で囲まないでください。

shopt...compat31

[[設定されている場合、bashは条件付きコマンドの=~演算子に対する引用符付き引数に関してバージョン3.1の動作に変更します。

与えられた例については、以下を試してください:

if [[ ! "$dimension" =~ ^[0123456789]+x[0123456789]+$ ]]; then
    printf '%s %s\n' "'$dimension'" 'is not a valid dimension.'
fi
  • regexは でアンカーする必要があります^...$。そうでない場合は、foo1x1fubar有効なディメンションと見なされます。

また、入力検証などには範囲を使用しないように注意してください0-9。特に、セキュリティに敏感なコンテキストでのサニタイズの場合は、多くのロケールで、これらの範囲には、従来よりも多くの文字 (または複数の文字で構成される照合要素) が含まれるためです (C/POSIX ロケールでは現在も含まれています)。

の場合=~bashglobasciirangesここでは役に立ちません。Ubuntu 19.10 のロケールでは、の有無にかかわらず、は0123456789 に加えて 1040 種類の文字に一致することen_GB.UTF-8がわかりました。少なくとも私の場合、それらはすべて 0 から 8 までの 10 進数字と何らかの関係がありますが、それは一般には保証されていません。bash[0-9]globasciiranges

一方、[[:digit:]]および は[0123456789]、POSIX 準拠のシステムでは 10 および のみに一致します。

sh次のように、標準の構文とワイルドカード パターンを使用してこれを行うこともできます。

valid_geometry() case $1 in
  (*[!x0123456789]* | *x | x* | *x*x*) false;;
  (*x*) true;;
  (*) false;;
esac
if ! valid_geometry "$dimension"; then
   ...
fi

または、ksh glob を使用する場合 (がなくても および でもbash -O extglobサポートされます)、次のようにしますbash[[extglob

if [[ $dimension != +([0123456789])x+([0123456789]) ]]; then
  ...
fi

答え2

さて、これはうまくいくようです:

if [[ ! "$dimension" =~ [0-9]+x[0-9]+ ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

しかし、なぜ一重引用符で囲むと機能しないのか疑問に思います。

if [[ ! "$dimension" =~ '[0-9]+x[0-9]+' ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

これが私の解決策です:

dimension="3x5"

regex='[0-9]+x[0-9]+'

if [[ ! "$dimension" =~ $regex ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

[0-9]+これで、正規表現を引用するために一重引用符を使用できるようになりましたが、[[ ]] 内から $regex を参照するときには二重引用符を避ける必要があります。ただし、 ..の省略形があるかどうかはまだわかりません。

関連情報