一重引用符内の正規表現 - 値が失われましたか? [閉鎖]

一重引用符内の正規表現 - 値が失われましたか? [閉鎖]

私が読んでいる本 - O'ReillyのBash Shell学習では、次のようにいくつかのコードを指定します。

if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then 

   howmany=$1

   shift
   ....
   ....
   etc

これはgrep検索ユーティリティを使用して、適切な$1パターンが一致するかどうかをテストします。この目的のために、^-[0-9][0-9]*$「最初の文字にダッシュと数字、オプションで1つ以上の数字が続く」と解釈される正規表現をgrepに提供します。一致するものが見つかると、一致が返され、grepテストは真になります。それ以外の場合は何も返されず、処理はテストに渡されgrepます。elif

シェルが$と*を解釈し、それを未修正の状態でgrepに渡すのを防ぐために、正規表現を一重引用符で囲みました。

それでは、正規表現が'^-[0-9]'一重引用符のように意味を失わないのはなぜですか?通常、一重引用符の中のすべての内容は意味を失います。

ご協力ありがとうございます。

ベストアンサー1

他のユーザーが既に特定の質問に回答していますが、追加します。

if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then 

これは、いくつかの理由で文字列が正規表現と一致するかどうかを確認する悪い方法です。

  1. echo任意のデータと一緒に使用することはできません
  2. 上記のようにパラメータ拡張を引用符で囲んでいないのは、分割$1+グローブ演算子です。
  3. grep入力全体の正規表現を一致させるのではなく、入力の各行を一致させます。たとえば、trueを返しますfoo\n-0\nbar
  4. 正規表現は長さがゼロに一致する可能性があるため、grep通常の場合にいくつかの出力を生成することを確認するのは間違っています(コマンドの置き換えは末尾の改行を削除することに注意してください)。grep -qの終了状態を使用して依存する方が良いですが、コマンドの置き換えも避けることをお勧めします。grep[
  5. コマンドは次のようにgrep単純化できます。grep -xE '-[0-9]+'

bash、(拡張された)正規表現一致のための専用演算子がありますksh93zsh3つすべて(bash-3.1を含む)で移植可能で安定して使用するには、構文は次のとおりです。

re='^-[0-9]+$'
if [[ $1 =~ $re ]]; then
  echo matches
fi

yashまた、zsh以下をサポートします。

if [ "$1" '=~' '^-[0-9]+$' ]; then
  echo matches
fi

文字列(デフォルト)正規表現を一致させるための標準コマンドは次のとおりですexpr

if expr " $1" : ' -[0-9]\{1,\}$' > /dev/null; then
  echo matches
fi

^(ではない$)はに暗黙的に含まれていますexpr。また、演算子$1として使用される値の問題を回避するために、先行スペース文字を使用しますexpr

また、正規表現が含まれると\(...\)動作に影響を与えますexpr

通常、awkこれを達成するには、他の標準/移植可能な方法を使用することをお勧めします(awk拡張正規表現の使用に注意してください)。

if STRING=$1 RE='^-[0-9]+$' awk '
  BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'; then
...

または、次の機能を使用してください。

re_match() {
  STRING=$1 RE=$2 awk '
    BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'
}

if re_match "$1" '^-[0-9]+$'

この場合、標準case構成を使用してこれを達成することもできます。

case $1 in
  ("" | *[!0-9-]* | [!-]* | - | ?*-*) ;;
  (*) echo match;;
esac

を使用するには、オプション(サポートされている場合は標準オプションではないため)と組み合わせて、改行で区切られたレコードの代わりにNULで区切られたレコードを処理するように指示できますgrep--nullほとんどのシェルには$1NULを含めることができないので安全です。

 if printf %s "$1" | grep --null -xq '-[0-9]+$'; then
   echo match
 fi

おすすめ記事