web-dev-qa-db-ja.com

条件でワイルドカードを使用して文字列の先頭に一致させる

変数に、長さが異なるテキストの文字列を満たそうとする。重要な文字列の部分は、最初の数文字です。

var1=hello  
if [ $var1 == hello ]; then  
    echo success  
fi

または

var1=hello  
if [ $var1 == h*o ]; then  
    echo success  
fi

出力:成功

しかし、私は最初の3文字程度を気にしているので、これは論理的に聞こえますが機能していません。

var1=hello  
if [ $var1 == hel* ]; then  
    echo success  
fi

出力:-bash:[:引数が多すぎます

最初の数文字しか気にしないので、次のことができます。

var1=hello 
if [ ${var1:0:3} == hel ]; then 
    echo success  
fi

それはうまくいくでしょうが、私はなぜそのエラーが発生するのかの説明と、考えられるより良い書かれた解決策を探しています。

5
EAG08

if*を使用すると、ファイル名が拡張されます。したがって、最初のインスタンスでは、h*oはおそらく現在のディレクトリ内のファイルと一致しているため、テストに合格しました。

hel*は複数のファイルに一致したため、ifコマンドの引数が多すぎます。

if [[ $var1 == hel* ]]; thenをお試しください

二重括弧はテストを正規表現に変換し、*ワイルドカードは期待どおりに機能します。

8
Paul

[ *は、grepfind、またはcatと同様の通常のコマンドです。 /binで見つけることができるはずです。別のプログラムであるため、シェルは引数を[を渡す前に通常の展開セットを実行します。

すでに述べたように、テストで*を使用しているため、グロブ拡張が発生しています。 'hel*'などの引用符を使用しても、[はパターンをサポートしていないため、これはおそらく期待どおりに機能しません。 h*oが機能している場合、現在のディレクトリにhelloという名前のファイルがあり、そのパターンに一致する他のファイルがないことが原因である可能性があります。 helloファイルがなくても機能する場合は、実装がおかしい可能性があり、スクリプトが他のシステムで失敗する可能性があります。

必要に応じて、いくつかのオプションがあります。 Bash、Zsh、およびその他の一部のシェルには、[[が組み込まれています。組み込みであるため、グロブ拡張の回避など、引数に特別な扱いを与えることができます。さらに、パターンマッチングを実行できます。試す

var1=hello  
if [[ "$var1" = hel* ]]; then  
    echo success  
fi

また、パターンを囲む引用符がないことに注意してください。引用符がない場合、hel*[[によってパターンとして扱われ、引用符(単一または二重)があると、"hel*"は文字どおりに扱われます。

[[のないシェルなど、より広い互換性が必要な場合は、grepを使用できます。

var1=hello
if echo "$var1" | grep -qe 'hel.*' ; then
    echo success
fi

ここでは[または[[は不要ですが、'hel.*'を囲む引用符は必要です。

*一部のシェルには実際に[が組み込まれていますが、これは効率化のためです。それはすべきシェルの通常の「マングリング」の対象となる引数を持つことを含め、個別の実行可能ファイルと同じように動作します。

1
8bittree

組み込みのbash正規表現を使用せずに正規表現をハックするために使用するトリックがあります。例は#2です。これが機能する方法は、grepが何にも一致しない場合、出力を返さない(つまり、存在しない文字列)ことです。したがって、2つのテストがあります。-zは「null文字列」を意味し、-nは「データあり」を意味します。

if [ -n "`echo $var1 | grep -e 'h.*o'`" ] ; then
  echo 'water found'
fi
1
Some Linux Nerd

これはどう ?

if [["$ var1" == "hel" *]]

文字列の比較を行う際は、引用符の外にワイルドカードを付けます。

0