使用set构造的bash通配符扩展



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构造。

这也可能是对lsegrep的不必要使用,只需使用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]$'

相关内容

  • 没有找到相关文章

最新更新