[az]アスタリスクが数字と一致するのはなぜですか?


13

現在のパスに3つのディレクトリがあります。

$ls
a_0db_data  a_clean_0db_data  a_clean_data
$ls a_*_data
a_0db_data:

a_clean_0db_data:

a_clean_data:

$ls a_[a-z]*_data
a_clean_0db_data:

a_clean_data:

最後のlsコマンドのみが一致すると予想しましたa_clean_data。なぜそれも含むものと一致しました0か?

bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)

2
正規表現とグロブの違いについて詳しくは、この質問をご覧ください。
テルドン

4
a_*_dataこのファイルのいずれかに一致したという事実は、あなたを驚かせませんでしたか?
クトゥルフ14

@Cthulhuあなたが私を得た!
user13107 14

回答:


29

[a-z]一部には、番号と一致するものではありません。それは*です。シェルグロビング正規表現を混同している可能性があります。

ツールが好きgrep(正規表現のさまざまな味を受け入れる基本、デフォルトでは-E、拡張用-PのためのPerlの正規表現

例(-v一致を反転)

$ ls a_[a-z]*_data | grep -v "[0-9]"
a_clean_data

bash正規表現を使用する場合、変数$refが整数かどうかをテストする方法の例を次に示します。

re='^[0-9]+$'
if ! [[ $ref =~ $re ]] ; then
  echo "error"
fi

bash regexを使用する方法は?(tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.htmlを参照)
user13107 14


21

問題は、なぜa_[a-z]*_data一致するのa_clean_0db_dataかということです。

これは4つの部分に分けられます。

  • a_先頭にマッチa_clean_0db_data残して、clean_0db_data一致させます

  • [a-z]範囲内の任意の文字に一致しますa-z(例:)、一致するcままにlean_0db_dataします

  • * 任意の数の文字に一致します。たとえば lean_0db

  • _data 末尾と一致します _data

正規表現で[a-z]*、a..zの範囲内の任意の数の文字(ゼロを含む)を意味しますが、正規表現ではなくシェルグロビングを扱っています。

正規表現が必要な場合、いくつかのfind実装にはそのための-regex述語があります。

find . -maxdepth 1 -regex "^.*/a_[a-z]*_data$"

これ-maxdepthは、検索結果を現在のフォルダーに限定するためだけです。正規表現はファイル名全体に一致するため^.*/、パス部分に一致するようにa を追加しました。


11

*シェルパターンでは、0個以上の文字に一致します。先行するatomの0個以上*を意味する正規表現演算子と混同しないでください。

*基本的なシェルパターンには正規表現に相当するものはありません。ただし、さまざまなシェルにはそのための拡張機能があります。

  • ksh持っています*(something)

    ls a_*([a-z])_data
  • bashwith shopt -s extglobまたはzshwithで同じことができますsetopt kshglob

    shopt -s extglob
    ls a_*([a-z])_data
  • ではzshextendedglob有効になって、#正規表現と等価です*

    setopt extendedglob
    ls a_[a-z]#_data
  • の最近のバージョンではksh93、globで正規表現を使用することもできます。ここに拡張正規表現があります:

    ls ~(E:a_[a-z]*_data)

[a-z]は、現在のロケールに応じて異なるものに一致することに注意してください。通常、ロケールでは26 aからzラテン語のアクセント記号なしの文字にのみ一致しCます。他のロケールでは、通常、より多くの一致があり、常に意味をなさない場合があります。お住まいの地域の文字と一致させるには、をお勧めします[[:alpha:]]


[a-z]Cロケールで一致した26文字よりも多く一致する例を挙げていただけますか?これを最後に見たときの記憶から、Unixバリアントで実際に使用されるすべてのエンコーディングは、ISO-646をベースとしていました(その後、ISO-8859-Xのようなエンコーディングの文字に直接使用される上位128コードは、 UTF-8やEUCファミリーなどのエンコーディング)。AIXでさえEBCDICロケールがありませんでした(少なくとも私が利用できる限り)。POSIX / UNIX標準で要求されているかどうかを見つけようとしたのを覚えていますが、その結果は覚えていません。
AProgrammer 14

1
@AProgrammerは、エンコードに依存せず、ソート順(LC_COLLATE)に基づいています。[a-z]一般に、そのエンコーディングのコードポイントがaとzのコードポイントの間にあるかどうかに関係なく、文字セットに含まれるロケールに(éまたはí必ずしもźではありません)を含めます。Cロケールのみが、コードポイント値に基づいたソート順を保証します。詳細については、この他の回答を参照してください。
ステファンシャゼラス

OK、私が逃したのは、現在の照合シーケンスに従って範囲が解釈されたことです。
AProgrammer 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.