空白ではなく正規表現

空白ではなく正規表現

bashのif文内で文字列を正規表現と一致させようとしています。コードは以下のように表示されます。

var='big'
If [[ $var =~ ^b\S+[a-z]$ ]]; then 
echo $var
else 
echo 'none'
fi

一致は、「b」で始まり、その後に空白以外の文字が1つ以上あり、az文字で終わる文字列でなければなりません。文字列の先頭と末尾を一致させることはできますが、\ Sは空白以外の文字と一致することはできません。助けてくれてありがとう。

答え1

GNU以外のシステムでは、以下は\S失敗を説明します。

これは\SPCRE(Perl Compatible Regular Expressions)の一部です。それは属していませんBRE(基本正規表現)またはERE(拡張正規表現)シェルに使用されます。

=~二重括弧テストの Bash 演算子は[[ERE を使用します。

通常の文字とは異なり、EREで特別な意味を持つ唯一の文字はです.[\()*+?{|^$Sそれほど特別ではありません。より基本的な要素で正規表現を作成する必要があります。

regex='^b[^[:space:]]+[a-z]$'

どこ角かっこ表現[^[:space:]] 等しい\SPCRE表現:

デフォルト\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ロケールで)で終わっていることを確認してくださいba-z

両方のテストは正の範囲(「非」範囲ではない)で実行されます。その理由は、いくつかの文字を否定すると、より多くの一致が生成されるためです。 UNICODE v8 には 120,737 文字が割り当てられています。範囲が 17 文字を否定する場合、120720 個のその他の可能な文字が許可されます。

中間文字が持つことができる文字の範囲を制限することをお勧めします(たとえば、その文字は空白ではありませんが、他の文字にすることができます)。

答え2

[[ $var =~ ^b[^[:space:]]+[abcdefghijklmnopqrstuvwxyz]$ ]]

一致する項目は[a-z]通常、ロケールによって異なります。いいえ(唯一)それの一つですabcdefghijklmnopqrstuvwxyz

perl(水平および垂直スペース)は、POSIXおよびbash EREの\S他の正規表現エンジンでも認識されます。[^[:space:]]

bashこれらの正規表現を一致させるには、システムの正規表現ライブラリを使用します。ただし、\S正規表現に演算子があるシステム(最近のGNUシステムなど)でも、次の理由で機能しません。

[[ x = \S ]]

bash呼び出しregcomp("S")

[[ x = '\S' ]]

bash呼び出しregcomp("\\S")(バックスラッシュ2個)

ただし、 bash-3.1 を使用する場合、または次のように bash-3.1 互換性を有効にする場合shopt -s compat31:

[[ x = '\S' ]]

ERE対応システムで動作します(空白以外の文字と一致)\S

$ bash -c "[[ x =~ '\S' ]]" || echo no
no
$ bash -O compat31 -c "[[ x =~ '\S' ]]" && echo yes
yes

別のオプションは、正規表現を変数に入れることです。

$ a='\S' bash -c '[[ x =~ $a ]]' && echo yes
yes

\S繰り返しますが、これは正規表現をサポートするPerlなどのシステムでのみ機能します。

この特定のコードに対応するPOSIXは次のとおりですbash

if expr " $var" : \
        ' b[^[:space:]]\{1,\}[abcdefghijklmnopqrstuvwxyz]$' \
   > /dev/null; then
  printf '%s\n' "$var"
else
  echo none
fi

または:

case $var in
  ([!b]* | *[!abcdefghijklmnopqrstuvwxyz] | *[[:space:]]* | "" | ? | ??)
    echo none;;
  (*) printf '%s\n' "$var"
esac

答え3

一般化する

# match any non-whitespace char--works in bash and `grep` too
[^\r\n\t\f\v ]

詳細

一致(空白以外の文字)は、明らかに正規表現や同様の正規表現では機能しません\S。したがって、空白以外の文字が1つ以上表示される場合は使用しないでください。bashgrep

# INSTEAD OF THESE (which do NOT work in bash or `grep`)

# match one or more non-whitespace chars
\S+
# or (same thing)
[\S]+

...これを使用してください:

bash空白以外の文字をすべて一致させる方法とgrep

# match one or more non-whitespace chars (DOES work in bash and `grep`!)
[^\r\n\t\f\v ]+

私はこれを学んだhttps://regex101.com/。ここをクリックしてください:https://regex101.com/r/kM041K/1、画面右側の「ヘルプ」セクションの下に次のように表示されます。

\S空白以外の文字と一致します(と同じ[^\r\n\t\f\v ])。

したがって、正規表現について疑問がある場合は、このウェブサイトにアクセスしてその内容を確認してください。

関連情報