带有集合构造的bash通配符扩展
Bash通配符扩展 我有一个目录,里面有三个文件。我想使用wilcar扩展来匹配program.c和program.o带有集合构造的bash通配符扩展,bash,perl,Bash,Perl,Bash通配符扩展 我有一个目录,里面有三个文件。我想使用wilcar扩展来匹配program.c和program.o casper@casper-PC ~ $ ls -ltr total 4 drwxr-xr-x+ 1 casper None 0 Apr 12 18:31 perl_lwp -rw-r--r-- 1 casper None 0 Apr 25 00:14 program.o -rw-r--r-- 1 casper None 0 Apr 25 00:14 program.c -
casper@casper-PC ~
$ ls -ltr
total 4
drwxr-xr-x+ 1 casper None 0 Apr 12 18:31 perl_lwp
-rw-r--r-- 1 casper None 0 Apr 25 00:14 program.o
-rw-r--r-- 1 casper None 0 Apr 25 00:14 program.c
-rw-r--r-- 1 casper None 0 Apr 25 00:14 program.log
这是行不通的
casper@casper-PC ~
$ ls -ltr | egrep program.[co]
这也不管用
casper@casper-PC ~
$ ls -ltr | egrep program.?
这行不通
casper@casper-PC ~
$ grep -r program.?
这确实有效——但我想使用bash大括号扩展,而不是perl
casper@casper-PC ~
$ ls -ltr | perl -nle 'print /(program.[co])/'
program.o
program.c
然而,我觉得奇怪的是,它同时匹配了这两个元素,因为我认为set构造将匹配o或c,然后在匹配后停止,您可以尝试添加行尾锚点,并将regex放在引号内。请注意,grep使用regex查找字符串而不是glob
ls -ltr | grep 'program\.[co]$'
使用
set-x
查看发生了什么。由于在引号外使用通配符(glob构造),shell在运行egrep
之前展开文件名
如果要将模式传递给程序,请将它们括在“单引号”中
不要混淆globbing和正则表达式——它们是不同的模式匹配机制。例如:,在正则表达式中,?
表示“前面模式的零个或多个”,而在全局搜索中,它只表示一个字符
program.?
在正则表达式中表示“program”,后跟字符串中某个可选的单个字符(
表示除换行符以外的任何字符之一)
program.?
在globbing中表示“program.”,后跟一个字符
egrep
接受正则表达式,而不是glob构造
这也可能是不必要地使用了ls
和egrep
,只需使用echo
:
echo program.[co]
program.c program.o
echo program.?
program.c program.o
这是因为echo
是一个内置的shell,shell可以进行全局搜索(通常比调用外部程序(如ls
)更有效)
现在,您的Perl代码段工作起来有两个原因。第一:您将模式括在单引号中,这不是为egrep
所做的
第二点:您恰好选择了正则表达式和globbing中唯一相同的模式,[]字符类表示法(尽管这里甚至存在差异)。默认情况下,Perl中的/../notation调用正则表达式匹配(m
)运算符
您希望Perl匹配在第一次匹配时停止,但是-nl
选项意味着它对来自管道的标准输入中的每一行执行循环中的print
语句
顺便说一句,Perl还有内置函数glob()
您可以尝试glob
ls-ltr*程序。[co]
甚至echo程序。[co]
无需grep
:ls-l程序。{c,o}
echo *|perl -nle 'print glob("program.[co]")'