Bash wildcard expansion.
I have a direcotry with three files in it. I want to use wilcar expansion to match program.c and 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
This does not work.
casper@casper-PC ~
$ ls -ltr | egrep program.[co]
Nor does this work.
casper@casper-PC ~
$ ls -ltr | egrep program.?
This does not work
casper@casper-PC ~
$ grep -r program.?
this does work - but I wanted to use bash brace expansion, not perl.
casper@casper-PC ~
$ ls -ltr | perl -nle 'print /(program.[co])/'
program.o
program.c
However I thought it strange that it matches both of them because I thought that the set construct would match o or c and then stop once it matched
Use set -x
to see what is happening. Since you are using wildcards ( glob constructs ) outside quotes, the shell expands the filenames before egrep
gets run.
If you want to pass patterns to a program, enclose them inside 'single quotes' .
Don't confuse globbing with regular expressions - they are different pattern matching regimes. For example:, in regular expressions ?
means "zero or more of the preceding pattern", whereas in globbing it means exactly one character.
program.?
in a regular expression means "program" followed by an optional single character ( .
means one of any character except newline) somewhere in the string .
program.?
in globbing means "program." followed by one single character.
egrep
takes regular expressions, not glob constructs.
This is also possibly an unnecessary use of both ls
and egrep
, just use echo
:
echo program.[co]
program.c program.o
echo program.?
program.c program.o
This works because echo
is a shell built-in and the shell does globbing (and is generally more efficient than calling an external program like ls
).
Now your Perl snippet worked for two reasons. One: you enclosed the pattern inside single quotes, which you didn't do for the egrep
.
Two: you just happened to pick the only pattern which is the same in regular expressions and globbing - the [ ] character-class notation (although there are even differences here). The /.../ notation in Perl invokes the regular expression match ( m
) operator by default.
You expected the Perl match to stop on the first match, but the -nl
options means that it performs the print
statement in a loop for each line in standard-input, which comes from the pipe.
BTW, Perl also has the built-in function glob()
.
echo *|perl -nle 'print glob("program.[co]")'
You could try adding end of the line anchor and also put the regex inside quotes. Note that grep uses regex to find strings not glob.
ls -ltr | grep 'program\.[co]$'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.