bashのif条件で正規表現を使用する


87

bashのif句で正規表現を使用するための一般的なルールはありますか?

ここに例があります

$ gg=svm-grid-ch  
$ if [[ $gg == *grid* ]] ; then echo $gg; fi  
svm-grid-ch  
$ if [[ $gg == ^....grid* ]] ; then echo $gg; fi  
$ if [[ $gg == ....grid* ]] ; then echo $gg; fi  
$ if [[ $gg == s...grid* ]] ; then echo $gg; fi  
$   

最後の3つが一致しないのはなぜですか?

この例だけでなく、できるだけ多くの一般的なルールを与えることができれば幸いです。

回答:


127

globパターンを使用する場合、疑問符は単一の文字を表し、アスタリスクは0個以上の文字のシーケンスを表します。

if [[ $gg == ????grid* ]] ; then echo $gg; fi

正規表現を使用する場合、ドットは単一の文字を表し、アスタリスクは直前の文字の0個以上を表します。したがって、「.*」は任意の文字の0個以上をa*表し、「」は0個以上の「a [0-9]*」を表し、「」は0個以上の数字を表します。もう1つの便利なもの(多くの中で)は、前の文字の1つ以上を表すプラス記号です。したがって、「[a-z]+」は1つ以上の小文字のアルファベット文字を表します(Cロケールでは-およびその他のいくつか)。

if [[ $gg =~ ^....grid.*$ ]] ; then echo $gg; fi

文字列照合には、グロブパターンと正規表現の2つの方法がありますか?glob petternはファイル名だけに使用されているのですか?bashでは、globパターンをいつ使用し、いつ正規表現を使用するのですか?ありがとう!
ティム

1
@Tim:Globbingは、Bashのほとんどまたはすべてのバージョンで使用できます。正規表現一致はバージョン3以降でのみ使用できますが、3.2以降でのみ使用することをお勧めします。正規表現は、グロビングよりもはるかに用途が広いです。
追って通知があるまで一時停止。



7

よりポータブルなソリューションに興味がある人のためにgrep、このソリューションと基本的なshビルトインを追加します(bashバージョンには依存shしません。Linux以外のプラットフォームで、古いバージョンでも動作します)。

# GLOB matching
gg=svm-grid-ch    
case "$gg" in
   *grid*) echo $gg ;;
esac

# REGEXP    
if echo "$gg" | grep '^....grid*' >/dev/null ; then echo $gg ; fi    
if echo "$gg" | grep '....grid*' >/dev/null ; then echo $gg ; fi    
if echo "$gg" | grep 's...grid*' >/dev/null ; then echo $gg ; fi    

# Extended REGEXP
if echo "$gg" | egrep '(^....grid*|....grid*|s...grid*)' >/dev/null ; then
  echo $gg
fi    

一部のgrepインカネーションは、-qへのリダイレクトの代わりに(静かな)オプションもサポートしています/dev/nullが、リダイレクトが最も移植性が高いです。


egrepの終了 ")"を忘れました
ghostdog74

5
grep -q代わりに使用しますgrep >/dev/null
bfontaine 2016年

3

@OP、

glob petternはファイル名だけに使用されているのですか?

いいえ、「glob」パターンはファイル名だけに使用されるわけではありません。文字列の比較にも使用できます。例では、case / esacを使用して文字列パターンを検索できます。

 gg=svm-grid-ch 
 # looking for the word "grid" in the string $gg
 case "$gg" in
    *grid* ) echo "found";;
 esac

 # [[ $gg =~ ^....grid* ]]
 case "$gg" in ????grid*) echo "found";; esac 

 # [[ $gg =~ s...grid* ]]
 case "$gg" in s???grid*) echo "found";; esac

bashでは、globパターンをいつ使用し、いつ正規表現を使用するのですか?ありがとう!

Regexは「globパターン」よりも用途が広く「便利」ですが、「globbing / extended globbing」では簡単に提供できない複雑なタスクを実行している場合を除き、regexを使用する必要はありません。Regexはbash <3.2のバージョンではサポートされていません(dennisが述べたように)が、拡張グロビングを使用できます(を設定することによりextglob)。拡張グロビングについては、ここといくつかの簡単な例を参照してください

OPの更新:正規表現を使用して、2文字(ドット "。"は1文字を意味します)で始まり "g"が続くファイルを検索する例

例:出力

$ shopt -s dotglob
$ ls -1 *
abg
degree
..g

$ for file in *; do [[ $file =~ "..g" ]] && echo $file ; done
abg
degree
..g

上記では、ファイル名に2文字の後に「g」が含まれているため、ファイルは一致しています。(すなわち..g)。

グロビングと同等のものは次のようになります:(およびの意味については参照参照してください?*

$ for file in ??g*; do echo $file; done
abg
degree
..g

ghostdog74に感謝します。3.2よりも高いバージョンのBashでは、正規表現を使用して、グロブパターンがどこにある場合でも置換できますか?または、正規表現はいくつかの特別な状況でのみ使用できますか?たとえば、「ls ?? g」は機能しているのに「ls ..g」は機能していないことがわかりました。
ティム

必要があれば、正規表現の使用を止めることはできません。それはあなた次第です。正規表現の構文はシェルグロビング構文とは異なることに注意してください。これls ..gは動作しません。という名前のファイルを探すようにシェルに指示しています..g。正規表現の構文についての学習のためとして、あなたは試すことができperldoc perlretutperldoc perlrequickまたは行うinfo sedコマンドラインで。
ghostdog74 2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.