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
-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-brace扩展,而不是perl。
casper@casper-PC ~
$ ls -ltr | perl -nle 'print /(program.[co])/'
program.o
program.c
然而,我觉得奇怪的是,它同时匹配它们,因为我认为集合结构会匹配o或c,然后一旦匹配就停止
使用set -x
查看发生了什么。由于您在引号外使用通配符(glob构造),shell在运行egrep
之前展开文件名。
如果要将模式传递给程序,请将它们括在"单引号"内。
不要把globbing和正则表达式混为一谈——它们是不同的模式匹配机制。例如:在正则表达式中,?
的意思是"前面模式的零个或多个",而在globing中,它的意思是正好一个字符。
正则表达式中的program.?
表示"程序",后面跟着一个可选的单个字符(.
表示除换行符外的任何字符之一)。
program.?
在globbing中的意思是"程序",后面跟一个字符。
egrep
采用正则表达式,而不是glob构造。
这也可能是对ls
和egrep
的不必要使用,只需使用echo
:
echo program.[co]
program.c program.o
echo program.?
program.c program.o
这是因为echo
是一个内置的shell,并且shell执行globbing(通常比调用像ls
这样的外部程序更高效)。
现在您的Perl代码段工作起来有两个原因。第一:您将模式括在单引号内,而egrep
没有这样做。
第二:您只是碰巧选择了仅的模式,这在正则表达式和globbing中是相同的-[]字符类表示法(尽管这里甚至有差异)。/…/Perl中的表示法默认调用正则表达式匹配(m
)运算符。
您希望Perl匹配在第一次匹配时停止,但-nl
选项意味着它在标准输入(来自管道)中的每一行的循环中执行print
语句。
顺便说一句,Perl还有内置的函数glob()
。
echo *|perl -nle 'print glob("program.[co]")'
您可以尝试添加行尾锚点,也可以将正则表达式放在引号内。注意,grep使用regex查找字符串,而不是glob。
ls -ltr | grep 'program.[co]$'