私はこの動作を理解するのが本当に難しいです。
stackExchange@test:~$ if [[ "two words" =~ \bwords ]]; then echo hi; fi; #(I'd expect this one worked)
stackExchange@test:~$ if [[ "two words" =~ \\bwords ]]; then echo hi; fi; #(or at least this one...)
stackExchange@test:~$ if [[ "two words" =~ \\\bwords ]]; then echo hi; fi;
stackExchange@test:~$ if [[ "two words" =~ \\\\bwords ]]; then echo hi; fi;
stackExchange@test:~$ put_in_a_variable=\\bwords
stackExchange@test:~$ if [[ "two words" =~ $put_in_a_variable ]]; then echo hi; fi;
hi
stackExchange@test:~$
\bword
私は変数が条件式のパターン部分に含まれて拡張されることを知っていますが、インラインシェルエスケープを使用して同じ動作を達成することが不可能に見える理由は本当に理解できません。
私はそのようなことをしたくありませんif [[ "two words" =~ $(echo \\bwords) ]]; then echo hi; fi;
。あまりにも奇妙です。
ありがとう、
フランシスコ
答え1
正規表現部分では、バックスラッシュの目的は次のとおり[[ str =~ rex ]]
です。引用する次の文字(一重引用符で囲んだように)、bash、およびバージョン3.2以降は、文字通り一致するように指示します(1)。b
特別ではないので、\b
ただb
、しかし'\'
、"\\"
またはリテラルバックスラッシュと一致させるために\\
なります:\\
[[ abwords =~ \bwords ]] && echo "<$BASH_REMATCH>"
<bwords>
[[ 'a\bwords' =~ \\bwords ]] && echo "<$BASH_REMATCH>"
<\bwords>
# conversely, '|' is just like \|
[[ 'a|words' =~ a'|'words ]] && echo "<$BASH_REMATCH>"
<a|words>
正規表現を変数に入れるアイデアがいいですね。別の方法は、ラッパー関数を使用することです。
rematch() [[ $1 =~ $2 ]]
if rematch 'two words' '\bwords\b'; then
echo "<$BASH_REMATCH>"
fi
<words>
とにかく、これらの回避策を適用した後は、非標準の拡張正規表現演算子\b
(perlによって提供されます)なので、動作するかどうかはシステムの正規表現ライブラリがそれをサポートしているかどうかによって異なります。システムによっては、\<
/\>
または[[:<:]]
/などの単語境界演算子の代替構文を使用する方が良い場合があります[[:>:]]
。
(1): 記録されるように手動:
パターンのすべての部分を引用して、引用された部分を文字列に一致させることができます。
シェルでは、文字は次のようになります。先頭実際には特別なマークしたがって、パーサによる後続の処理は、文字列の一部が引用されているかどうかによって決定することができる。