*
on its own is an invalid regular expression since there is no previous item to repeat. Your implementation of grep, in this case, interprets it as a literal *
. \*
is a valid regular expression which matches a *
. Your implementation's interpretation of the invalid regular expression *
and the valid regular expression \*
just happen to be the same.
If you really want to see the difference between *
and \*
, you should try it on a valid regular expression by adding an item before it. For example, a literal a
:
grep 'a*'
grep 'a\*'
The former will match anything since *
can match zero characters successfully. The latter will only match lines containing a*
literally.