echo [[:digit:]] に予期しない動作があります。

echo [[:digit:]] に予期しない動作があります。

私は尋ねたい:

echo {1,2,3}予想される動作である1 2 3に展開し、からのすべての数字を印刷すると予想されるときに返されるのecho [[:digit:]]はなぜですか?[[:digit:]]09

答え1

なぜなら、彼らは異なっているからです。これは{1,2,3}例です支柱の拡張。これは{1,2,3}延長されました。シェルを通してecho見る前に。次のコマンドを使用すると、何が起こるかを確認できますset -x

$ set -x
$ echo {1,2,3}
+ echo 1 2 3
1 2 3

ご覧のとおり、コマンドはecho {1,2,3}次のように拡張されます。

echo 1 2 3

しかし[[:digit:]]それはPOSIX 文字クラス。渡すとechoシェルでも先に処理しますが今回は で処理されます。シェルボール。実行と同じように機能し、echo *現在のディレクトリのすべてのファイルを印刷します。しかし、[[:digit:]]どの数字とも一致できるシェルグローブです。 bashでは、シェルglobが何も一致しない場合、それ自体が拡張されます。

$ echo /this*matches*no*files
+ echo '/this*matches*no*files'
/this*matches*no*files

globが何かと一致すると、次のように印刷されます。

$ echo /e*c
+ echo /etc
/etc

どちらの場合も、echoシェルが印刷するように指示するものは何でも印刷しますが、2番目の場合はglobが何か(/etc)と一致するため、それを印刷するように指示されます。

[[:digit:]]したがって、名前が1桁の数字(一致する数字)で構成されるファイルやディレクトリがないため、globは独自に拡張され、次のようになります。

$ echo [[:digit:]]
[[:digit:]]

それでは、次のファイルを生成し5て同じコマンドを実行してみてください。

$ echo [[:digit:]]
5

一致するファイルが複数ある場合:

$ touch 1 5       
$ echo [[:digit:]]
1 5

これはman bash、この動作をオフにするオプションの説明に(やや)文書化されています。nullglob

nullglob
    If  set,  bash allows patterns which match no files (see
    Pathname Expansion above) to expand to  a  null  string,
    rather than themselves.

このオプションを設定する場合:

$ rm 1 5
$ shopt -s nullglob
$ echo [[:digit:]]  ## prints nothing

$ 

答え2

{1,2,3}はい支柱の拡張、意味に関係なく、リストされた単語に展開されます。

[...]は、次の目的で使用される文字のグループです。ファイル名拡張子(またはワイルドカードまたはワイルドカード)は、アスタリスク*と疑問符に似ています?。ここにリストされている単一文字または名前付きグループのメンバーである文字(たとえば、リストされている文字のいずれ[:digit:]か)と一致します。ほとんどのシェルのデフォルトの動作は、一致するファイルがない場合はワイルドカードを残すことです。

(ワイルドカード/パターンを一致させたい文字列セットに実際に変換することはできません。アスタリスクは任意の長さの文字列と一致する可能性があるため、それを含むパターンを展開すると無限の文字列のリストが生成されます。)

だから:

$ bash -c 'echo [[:digit:]]'           # bash leaves it as-is
[[:digit:]]
$ zsh -c 'echo [[:digit:]]'            # zsh by default complains if no match
zsh:1: no matches found: [[:digit:]]
$ touch 1 3 d i g t
$ bash -c 'echo [[:digit:]]'           # now there are two matches
1 3                                    # note that d, i, g and t do NOT match

しかし、まだ:

$ bash -c 'echo {1,2,3}'
1 2 3

どちらもシェルに拡張されます。lsecho、実行するコマンドが、または、または認識は重要ではありませんrm。また、次のいずれかを参照しても拡張されません。

$ bash -c 'echo "[[:digit:]]"'         # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}

答え3

{1,2,3}{1..3}例えば支柱の拡張。コマンドが実行される前にシェルによって解釈されます。

[[:digit:]]パターンマッチングトークンですが、そのパターンと一致するファイルの場所では使用していません。一致なしでパターン一致を使用すると、それ自体が拡張されます。

$ echo [[:digit:]]; touch 3; echo [[:digit:]]
[[:digit:]]
3

関連情報