初めてのbashスクリプトなので、たぶん簡単な間違いを犯しています。
基本的に、ユーザーのグループを取得するスクリプトを記述しようとしています。特定のグループに属している場合は、それに応じてログに記録されます。明らかにより多くの機能があるでしょうが、私が正規表現さえも動作させることができないときにそれを構築する意味はありません!
これまでのところ、私はこれを持っています:
#!/bin/bash
regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
# example output
groups="username : username usergroup"
echo "$groups" >> /home/jrdn/log
if [[ "$groups" =~ $regex ]]; then
echo "Match!" >> /home/jrdn/log
else
echo "No match" >> /home/jrdn/log
fi
私がその正規表現を試したすべての場所で動作します。しかし、bashスクリプトでは、$groups
、 に続く No match
。だから誰かがそれの何が悪いのか教えてもらえますか?
man 7 regex
から:
大括弧式は、「[]」で囲まれた文字のリストです。 …
…リテラル「-」を含めるには、最初または最後の文字にします…。 [A] '\'を含む他のすべての特殊文字は、ブラケット式内の特別な意味を失います。
Egrepで正規表現を試行するとエラーが発生します。
$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end
これは、エラーも発生する単純なバージョンです。
$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end
\
は特別なものではないため、[a-z]
と同様に、これは範囲です。 -
のように、末尾に[_-]
を付ける必要があります。または:
echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup
これは、libcのバージョン(egrepまたはbash)に関係なく機能するはずです。
編集:実際のロケール設定にも依存します。マンページはこれについて警告します:
範囲は照合順序に非常に依存するため、移植可能なプログラムは範囲に依存しないようにする必要があります。
例えば:
$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_
もちろん、エラーは発生しませんでしたが、意図したとおりに動作していません。
$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_
これは、ASCIIでは\
、[
、^
、および_
を含む範囲です。
正規表現(およびコードの大きな部分にあるバグ)の一般的なルール:それを切り下げて、段階的に再構築するか、二分法を使用します。
この場合、犯人はアンダースコアであることが判明しました-バックスラッシュでエスケープすると機能します。