*
私はここで非常にマイナーな問題に固執しました:bashでシンボルを意味する方法0以上、ツールのようなsed
?
たとえば、名前ak*
全体がa
ゼロ個以上のsでk
構成されているファイルはすべて一致する必要があります。拡張子には、およびが含まれますa
が、ak
含まれakk
ませakkk
んakc
。
私はこれをunsetopt sh_glob
zshとset -o noglob
bashで試しましたが、予想される動作を生成しません。
答え1
とは別にksh93
、一般的に使用されるシェルには、ファイルの一致に使用できるsed、awkなどと同じ構文を持つ正規表現はありません。
Ksh93、bash、zshは構文が異なる正規表現を持ち、globと逆互換です。
?
単一文字と一致します(.
通常の正規表現構文と同じ)。[…]
ほぼ同じ方法で文字セットを一致させます。*(FOO)
ランダムな発生数の一致FOO
(通常の正規表現構文と同じ)(FOO)*
- また、1つ以上の項目と一致し、ゼロまたは1つの項目と一致します。
+(FOO)
?(FOO)
@(FOO|BAR)
一致FOO
するBAR
- 部分文字列ではなく文字列全体に対して一致が機能します。部分文字列が必要な場合は、
*
開始と終了に入れてください。
shopt -s extglob
この構文を使用するには、bashとzshで有効にする必要がありますsetopt ksh_glob
。だからbashでは、次のように書きます。
shopt -s extglob
ls a*(k)
また、見ることができます私の正規表現がXでは動作しますが、Yでは動作しないのはなぜですか?
=~
Ksh93、zsh、bashは、拡張正規表現(デフォルトではawk構文)を含む生成された演算子を使用して、文字列の正規表現一致を実行できます[[ … ]]
。これはファイルのリストを表示するのに不便ですが、本当に必要に応じて行うことができます。
shopt -s dotglob # <<< include dot files, for bash
setopt globdots # <<< include dot files, for zsh
FIGNORE='@(.|..)' # <<< include dot files, for ksh
for x in *; do
if [[ $x =~ ^ak*$ ]]; then
…
fi
done
答え2
ls ak{k,}
ak
で始まるファイルが表示され、その後に他のファイルが表示されるか、k
ファイルは表示されません。
$ touch ak akk akc
$ ls -l ak{k,}
-rw-rw-r-- 1 cas cas 0 Oct 27 10:30 ak
-rw-rw-r-- 1 cas cas 0 Oct 27 10:30 akk
globは正規表現ではありませんが、単純な*
and以上の機能を果たします?
。
正規表現を使用して一致するファイル名を見つけるには、次のfind
コマンドを使用できます。
$ find . -maxdepth 1 -type f -regex './ak+$'
./ak
./akk
この-maxdepth 1
オプションは、検索を現在のディレクトリにのみ制限します(サブディレクトリは検索されません)。
大文字と小文字を区別せずに検索するには、-iregex
代わりにを使用してください-regex
。
find
他のコマンドで見つかったファイルを使用する方法はいくつかあります。たとえば、
find . -maxdepth 1 -type f -regex './ak+$' -ls
find . -maxdepth 1 -type f -regex './ak+$' -exec ls -ld {} +
find . -maxdepth 1 -type f -regex './ak+$' -print0 | xargs -0r ls -ld
ls -ld $(find . -maxdepth 1 -type f -regex './ak+$')
最後の例は、1.ファイル名などのスペースを処理しない、2.コマンドラインの長さの制限など、さまざまなエラーモードに脆弱です。お勧めできません。
答え3
使用できる構文はbash
次のとおりです。
ls a+(k)
これは有効なシェルオプションによって異なりますbash
shopt
。extglob
Ubuntu 14.04 GNU / Linuxでは、これはデフォルトで有効になっているようです。
仕組みは次のとおりです。
$ shopt extglob
extglob on
$ ls
ak akc akd akk akkk akkkk
$ ls a+(k)
ak akk akkk akkkk
$ shopt -u extglob
$ shopt extglob
extglob off
$ ls a+(k)
bash: syntax error near unexpected token `('
$
Bashのマニュアルから:
+(モードリスト)
与えられたパターンと1つ以上一致します。
パターンリストは、「|」で区切られた1つ以上のパターンのリストです。
Bashのマニュアルを参照してください。https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching。
答え4
シェルによるいくつかのオプション:
$ touch a akk aka
$ ksh -c 'echo a*(k)'
a akk
$ zsh -o kshglob -o nobareglobqual -c 'echo a*(k)'
a akk
(nobareglobqual
ここでは末尾はグローバル(k)
修飾子とは見なされません)
$ bash -O extglob -c 'echo a*(k)'
a akk
$ zsh -o extendedglob -c 'echo ak#'
a akk
zsh
#
正規表現と同じです*
。
ksh93
また、対応するglobでさまざまな種類の正規表現を使用できます。
$ ksh93 -c 'echo ~(E:ak*)' # extended RE
a akk
$ ksh93 -c 'echo ~(P:ak*)' # perl-like RE
a akk
$ ksh93 -c 'echo ~(X:ak*)' # AT&T augmented RE
a akk
$ ksh93 -c 'echo @(~(E)ak*)' # alternative syntax
a akk