bashの[[ ]]
構造について知っておくべき重要なことがいくつかあります。最初:
単語分割とパス名展開は、間の単語に対して実行されていない[[
と]]
。チルダ展開、パラメーターおよび変数展開、算術展開、コマンド置換、プロセス置換、および引用符の削除が実行されます。
2番目のこと:
追加の二項演算子「=〜」が使用可能です...演算子の右側の文字列は拡張正規表現と見なされ、それに応じて照合されます...パターンの任意の部分を引用して、強制的に照合することができます文字列として。
その結果、の$v
いずれかの側で=~
その変数の値に展開されますが、結果はワード分割またはパス名展開されません。言い換えると、左側で変数の展開を引用符で囲まずに残すことは完全に安全ですが、変数の展開は右側で発生することを知っておく必要があります。
したがって、次のように記述した場合、右側の正規表現[[ $x =~ [$0-9a-zA-Z] ]]
の$0
内部は、正規表現が解釈される前に展開されます。これにより、正規表現のコンパイルに失敗する可能性があります($0
ASCII値がより小さい数字または句読記号で終了する場合を除く)。数字)。-soのように右側を引用すると、右側[[ $x =~ "[$0-9a-zA-Z]" ]]
は正規表現ではなく通常の文字列として扱われます(さらに$0
展開されます)。この場合に本当に必要なのは[[ $x =~ [\$0-9a-zA-Z] ]]
同様に、間の発現[[
と]]
正規表現が解釈される前の単語に分割されます。したがって、正規表現内のスペースはエスケープまたは引用符で囲む必要があります。文字、数字、またはスペースを一致させたい場合は、次を使用できます[[ $x =~ [0-9a-zA-Z\ ] ]]
。#
引用されていない場合はコメントを開始するなど、他の文字も同様にエスケープする必要があります。もちろん、パターンを変数に入れることができます。
pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...
bashのレクサーを通過するためにエスケープまたは引用符で囲む必要のある文字が多数含まれている正規表現の場合、多くの人がこのスタイルを好みます。ただし、注意してください。この場合、変数展開を引用することはできません。
if [[ $x =~ "$pat" ]]; then ...
最後に、あなたがやろうとしていることは、変数に有効な文字だけが含まれていることを確認することだと思います。このチェックを行う最も簡単な方法は、無効な文字が含まれていないことを確認することです。言い換えると、次のような式です。
valid='0-9a-zA-Z $%&#'
if [[ ! $x =~ [^$valid] ]]; then ...
!
テストを否定し、「一致しない」演算子に変換します。[^...]
正規表現文字クラスは、「以外の文字」を意味し...
ます。
パラメータ展開と正規表現演算子の組み合わせにより、bashの正規表現構文を「ほぼ読み取り可能」にすることができますが、まだいくつかの落とし穴があります。(いつもあるのではないですか?)一つは、引用さ]
れた$valid
としても、$valid
最初を除いて、入れることができなかったということです。(これはPosixの正規表現ルールです。]
文字クラスに含める場合は、最初に配置する必要があります。-
最初または最後に移動できます。したがって、との両方が必要な場合は]
、-
で開始し]
て終了する必要があります-
。正規表現につながる絵文字を「私は私がやっているか知っています」: [][-]
)