カンマ区切りの数字と一致するグローバルパターン

カンマ区切りの数字と一致するグローバルパターン

カンマで区切られた数字と一致するグローバルパターンを作成したいと思います。パターンはどんな姿なのでしょうか?

ここにいくつかの例があります。

5
5,8,13

次に始めましたが、一致するものを取得できないため、いくつかの問題があります。

var="8,13,21"
echo "var: $var"
if [[ "$var" == ^*([[:digit:]])+(,+[[:digit:]])$ ]]; then
  echo "match"
fi

答え1

bashのマニュアルは[[ expression ]]構文を説明します。

==AND演算子を使用すると、!=演算子の右側の文字列はパターンとして扱われ、シェルオプションが有効になっている extglob かのように、パターンの一致で説明されている規則に従って一致します。

ここで、シェルオプションはextglobksh スタイル拡張グローブを表します。

  ?(pattern-list)
         Matches zero or one occurrence of the given patterns
  *(pattern-list)
         Matches zero or more occurrences of the given patterns
  +(pattern-list)
         Matches one or more occurrences of the given patterns
  @(pattern-list)
         Matches one of the given patterns
  !(pattern-list)
         Matches anything except one of the given patterns

私が疑うのは、+[[:digit:]]1つ以上の数字を一致させることです+([[:digit:]])。したがって、カンマの後に1つ以上の数字が続き、すべて0回以上でなけれ*(,+([[:digit:]])ばなりません。

+([[:digit:]])*(,+([[:digit:]]))

カンマで区切られたリストを形成するには、1つ以上の数字と0つ以上のカンマで区切られた数字が続く一致を見つけます。

^glob式はアンカーを使用しないことに注意してください$。これは常に完全な行です。部分一致が必要な場合は、*式をワイルドカードで囲む必要があります。


1 これはbash 4.1以降の新機能です。以前のバージョンでは、shopt -s extglobこれらの拡張グローバル演算子を内部および外部で明示的に使用できるようにする必要がありました[[...]]

答え2

使用する構文は、ワイルドカードと正規表現構文が混在しているようです。

BashのRegEx一致を使用したい場合(上記のように)コメントから)、比較演算子を使用する必要があります=~。この場合、テスト構成の正しい構文は次のとおりです。

if [[ "$var" =~ ^([[:digit:]])+(,[[:digit:]]+)*$ ]]; then
...

これはいくつかの点で実証された試みとは異なります。

  • 現在の試みでは、,+[[:digit:]]「1つ以上のカンマと数字」が一致します。
  • 最初にRegExが*迷子になったようです。リテラルと一致しない限り、*間違っているか(*RegExでは「可能な文字の組み合わせ」ではなく「0個以上の先行文字」を意味します)、重複しています。 (一致させるには、$.*アンカーを削除して単に宣言することもできます([[:digit:]])+(,+[[:digit:]])$)。

一方、実際に「拡張されたワイルドカード」構文(演算子の設定[[ ... ]]でデフォルトで許可されている==)を使用したい場合

  • ^アンカー(および)の使用が$正しくありません。アンカーは正規表現にのみ有効で、拡張形式でもグロービング構文の一部ではありません。また、グローバルパターンは基本的に文字列全体に適用されるため、必要ありません。
  • また、すべて「繰り返し指定子」(たとえば、*または+)の前にある項目は括弧内に配置する必要があるため、ステートメントに括弧セットがありません+[[:digit:]]

したがって、この場合、一致するグローブは次のようになります。

if [[ "$var" == +([[:digit:]])*(,+([[:digit:]])) ]]; then echo "match"; fi

答え3

sh完璧にするために、ステートメントで標準ワイルドカードcase(kshism)を使用してこれを行うには、[[...]]その逆を実行する必要があります。

case $var in
  ('' | *[!,0123456789]* | *, | ,* | *,,* ) echo WRONG;;
  (*) echo RIGHT;;
esac

+標準のglobモード(##zshまたはkshと同じ)にはEREと同等の機能はありません。+(...)

ただし、次のコマンドを使用して正規表現の一致を実行できますawk

rematch() { awk -- 'BEGIN{exit(ARGV[1] !~ ARGV[2])}' "$@"; }

if rematch ",$var" '^(,[0123456789]+)+$'; then
  echo RIGHT
else
  echo WRONG
fi

1 ANSI Cエスケープシーケンス(例awk: 。 。\n\t\b

関連情報