In Bash, when you type ls *.out
, it will output the list which ended with .out
. Is this a regular expression?
If yes; when I echo a.out > test
and then type grep *.out test
, it outputs nothing.
Is *
in the ls same *
in the regex?
In Bash, when you type ls *.out
, it will output the list which ended with .out
. Is this a regular expression?
If yes; when I echo a.out > test
and then type grep *.out test
, it outputs nothing.
Is *
in the ls same *
in the regex?
The main thing to understand is that your shell is expanding program arguments (passed to main
function of executed programs). Read Bash chapter about shell expansions (and globbing)
So you should not type ls "*.out"
but just ls *.out
then the /bin/ls
program is started with the expansion of *.out
. For example, if you have files a.out
, b.out
, cc.out
, a.c
the expansion of *.out
(done by the shell) is a.out
b.out
cc.out
so /bin/ls
gets "ls"
"a.out"
"b.out"
"cc.out"
followed by NULL
as its char**argv
second argument to its main
, with the first int argc
argument being 4.
But grep
indeed want some regular expression or "regexp". You generally want to quote it (to avoid the shell to try its expansion).
It's the shell that expands the filename globs, so in both ls *.out
and grep *.out test
the shell fills the filenames to the command line, and the command itself only sees the resulting list of names. Assuming you have files called foo.out
and bar.out
, those commands would be equivalent to these:
ls bar.out foo.out
grep bar.out foo.out test
The first one asks ls
to list the files, the second asks grep to look for the pattern bar.out
in the files foo.out
and test
. The latter is probably not what you want, so quote the pattern for grep:
grep "*.out" test
Except that that is not really a valid regular expression. In filename globs, the asterisk *
matches zero or more characters, in regular expression it matches zero or more of the previous item (character, character group or expression in parenthesis), but at the start of line there aren't any, so the expression makes little sense. Perl complains about that, grep
and sed
don't, but they also don't seem to match anything.
In regexes, the dot .
means any character, so needs to be escaped to be taken literally. Also, grep finds matches anywhere in the line, so the leading .*
(which would match any number of any characters) can be omitted. So this would look for lines containing the string .out
in the file test
:
grep "\.out" test
As we saw, the patterns used by Bash and the patterns (regular expressions) used by grep are not the same. See e.g. Bash's manual for the pattern matches used in filename expansion and the man page regex(7)
for regular expressions. Also note that there are different dialects of regexes, which aren't fully compatible with each other.
By default, grep looks for the exact expression, not a regular expression, but you can tell it to look for a regular expression by adding the -E
flag.
So I think what you're looking for is grep -E *.out test
, though a little bit of research on the net would've given you what you wanted ;)
For grep command, * means 0 or more occurences of prev/preceding character or expression. So in your case grep .out* test
would work as it will look for the occurrence of .ou
followed by 0 or more occurrence of any character in the file test.
For ls command, ls *.out
would mean list all the files/folders ending with their name as .out
.