bashスクリプトの正規表現


13

これは初めての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ます。だから誰かが私に何が悪いのか教えてもらえますか?


1
何が悪いと思いますか?
マナトワーク

1
@jrdnhannahは、ターゲットの正規表現をゆっくりと再作成し、最初に一致し^([a-zA-Z0-9\-_]+)てからコロンを追加するなど...すぐに問題の場所を見つける必要があります。
ペテルフ

2
bash 4.2.45でも同じです。アンダースコアをエスケープすると修正されました。奇妙な。@jrdnhannahそれを答えとして書いて受け入れてください。
テルドン

1
私はUnix SEにサインアップしたばかりなので、自分自身に回答するまで8時間待つ必要があります。ただし、他の誰かが回答した場合は、回答済みとしてマークできます。
jrdn

4
@terdon bashは、おそらくlibcの正規表現関数を呼び出すだけです。そのため、bashバージョンではなくlibcバージョンに依存します。私の答えを参照してください...(または、使用中の照合シーケンスでさえ)
-derobert

回答:


14

から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で、含まれる範囲、だ\[^、と_


面白い。私egrepはエラーを出さず、正しく一致します。
マナトワーク

@manatwork照合シーケンスはおそらく範囲を許可します
。...-derobert

照合についてはあまり知りません。あなたはこれを意味します:LC_COLLATE="en_US.UTF-8"
マナトワーク

@manatwork質問を編集して例を示しました。これらの照合(ソート)シーケンスが変更される場合があるため、システムによって異なる場合があります。
デロバート

1
私は脱出しようとする試みに気づい前@manatworkそのOK、私はほとんどバグレポートを提出し-...
derobert

4

正規表現(およびコードのより大きな部分のバグ)を使用した一般的なルール:ステップごとに切り詰めて再構築するか、二分法を使用します。

この場合、犯人はアンダースコアであることが判明しました-バックスラッシュでエスケープすると動作します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.