bashのif文内で文字列を正規表現と一致させようとしています。コードは以下のように表示されます。
var='big'
If [[ $var =~ ^b\S+[a-z]$ ]]; then
echo $var
else
echo 'none'
fi
一致は、「b」で始まり、その後に空白以外の文字が1つ以上あり、az文字で終わる文字列でなければなりません。文字列の先頭と末尾を一致させることはできますが、\ Sは空白以外の文字と一致することはできません。助けてくれてありがとう。
ベストアンサー1
GNU以外のシステムでは、以下は\S
失敗を説明します。
これは\S
PCRE(Perl Compatible Regular Expressions)の一部です。それは属していませんBRE(基本正規表現)またはERE(拡張正規表現)シェルに使用されます。
=~
二重括弧テストの Bash 演算子は[[
ERE を使用します。
通常の文字とは異なり、EREで特別な意味を持つ唯一の文字はです.[\()*+?{|^$
。S
それほど特別ではありません。より基本的な要素で正規表現を作成する必要があります。
regex='^b[^[:space:]]+[a-z]$'
どこ角かっこ表現[^[:space:]]
等しい\S
PCRE表現:
デフォルト\s
の文字はHT(9)、LF(10)、VT(11)、FF(12)、CR(13)、スペース(32)です。
テストは次のとおりです。
var='big' regex='^b[^[:space:]]+[a-z]$'
[[ $var =~ $regex ]] && echo "$var" || echo 'none'
しかし、上記のコードはbißß
例えば一致します。これは、範囲に選択されたロケール(UNICODE)[a-z]
以外の文字が含まれるためです。abcdefghijklmnopqrstuvwxyz
これらの問題を回避するには、次を使用します。
var='bißß' regex='^b[^[:space:]]+[a-z]$'
( LC_ALL=C;
[[ $var =~ $regex ]]; echo "$var" || echo 'none'
)
コードはリスト内の文字(abcdefghijklmnopqrstuvwxyz
最後の文字の位置)だけと一致しますが、中央にある他の多くの文字(など)とも一致しますbég
。
ただし、この使用法はLC_ALL=C
他の正規表現の範囲に影響します。[[:space:]]
Cロケールでは空白のみが一致します。
すべての問題を解決するには、各正規表現を分離する必要があります。
reg1=[[:space:]] reg2='^b.*[a-z]$' out=none
if [[ $var =~ $reg1 ]] ; then out=none
elif ( LC_ALL=C; [[ $var =~ $reg2 ]] ); then out="$var"
fi
printf '%6.8s\t|' "$out"
内容は次のとおりです。
- input(var) にスペースがない場合 (現在のロケールで)
- aで始まり(Cロケールで)で終わっていることを確認してください
b
。a-z
両方のテストは正の範囲(「非」範囲ではない)で実行されます。その理由は、いくつかの文字を否定すると、より多くの一致が生成されるためです。 UNICODE v8 には 120,737 文字が割り当てられています。範囲が 17 文字を否定する場合、120720 個のその他の可能な文字が許可されます。
中間文字が持つことができる文字の範囲を制限することをお勧めします(たとえば、その文字は空白ではありませんが、他の文字にすることができます)。