2

I am using a simple text file to test the * meta-character through grep. The text file is as below:

1
11
111
1111
11111
111111

d
da
daa
daaa

b
bc
bcc
bccc

Now when I search digit 1 using grep like this:

grep 1* regex.txt

output is

1
11
111
1111
11111
111111

d
da
daa
daaa

b
bc
bcc
bccc

Even in the case of character 'd' the result is same with highlighted 'd' in red BUT in the case of character 'a' & 'b' there is no output for the following search command:

grep a* regex.txt
grep b* regex.txt

AND the below commands give expected output

grep "a*" regex.txt
grep "b*" regex.txt

Why so? Why is bash partial towards the character 'd' and not to 'a' & 'b'

3
  • 2
    Without quotes * is expanded by shell path. If there is no output for a* try echo a* and you should see files with names started with a (same b)
    – Costas
    Nov 14, 2015 at 9:57
  • 1. quote your regexps so the shell doesn't interpret them as wildcard globs. 2. regexps are not wildcard globs. * means zero-or-more of the last character/sub-expression. It does not mean "followed by anything" as it does in a shell wildcard.
    – cas
    Nov 14, 2015 at 10:16
  • Please don't edit your question to add a second question. Post a new question instead. I also suggest you read a basic primer on regular expressions to understand how they work a bit better. Try regular-expressions.info.
    – terdon
    Nov 14, 2015 at 12:10

1 Answer 1

4

This is happening because the a* and b* are not quoted and, therefore, are expanded by the shell before being passed to grep. For example, consider this directory:

$ ls    
afile.txt bfile.txt regex.txt

If I try to run grep a* regex.txt, the a* will become afile.txt and that is what will be given as a search pattern to grep. We can use bash's debugging option (set -x) to demonstrate:

$ set -x
$ grep a* regex.txt
+ grep --color afile.txt regex.txt

The reason it worked for d and not for a or b is that you have a files or directories whose names start with a and b in your current directory. If you didn't, it would have worked:

$ ls
afile.txt bfile.txt regex.txt
$ grep a* regex.txt  ## no output, it's searching for 'afile.txt'
$ rm afile.txt       ## now there are no filenames starting with a
$ grep a* regex.txt
1
11
111
1111
11111
111111

d
da
daa
daaa

b
bc
bcc
bccc

To avoid this, always quote your search patterns:

grep "a*" regex.txt

Or

grep 'a*' regex.txt
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .