Kir*_*ira 10 shell regular-expression wildcards
我在这里遇到了一个非常微不足道的问题:如何使*
bash 中的符号表示零或更多,就像在诸如sed
? 之类的工具中一样?
例如,ak*
应该匹配名称完全由a
后跟零个或多个k
s组成的任何文件。它的扩张将包括a
,ak
,akk
,和akkk
,但不会akc
。
我已经unsetopt sh_glob
在 zsh 和set -o noglob
bash 中尝试过;他们没有产生预期的行为。
Gil*_*il' 12
除了ksh93
,通常的 shell 都没有与 sed、awk 等语法相同的正则表达式,可用于匹配文件。
Ksh93、bash 和 zsh 的正则表达式具有不同的语法,可向后兼容 globs:
?
匹配任何单个字符(就像.
通常的正则表达式语法)[…]
以几乎相同的方式匹配字符集*(FOO)
匹配任意次数的FOO
(就像在通常的正则表达式语法中一样)(FOO)*
+(FOO)
?(FOO)
@(FOO|BAR)
匹配FOO
或BAR
*
开头和结尾此语法需要使用shopt -s extglob
in bash 和setopt ksh_glob
in zsh激活。所以在 bash 你会写
shopt -s extglob
ls a*(k)
Run Code Online (Sandbox Code Playgroud)
ksh93、zsh 和bash 可以用construct的=~
操作符对字符串进行正则表达式与扩展正则表达式(基本上是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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
globs 不是正则表达式,但它们不仅仅是*
and ?
。
如果要使用正则表达式查找匹配的文件名,可以使用以下find
命令:
$ find . -maxdepth 1 -type f -regex './ak+$'
./ak
./akk
Run Code Online (Sandbox Code Playgroud)
该-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+$')
Run Code Online (Sandbox Code Playgroud)
最后一个例子容易出现各种失败模式,包括 1. 不处理文件名中的空格等,2. 命令行长度限制。不建议。