I've created simple text file named "T" to test the unusual behavior of grep
:
1 Debug
2 debug
3 determined
4 Determined
Tried different syntax:
$ grep De T
1 Debug
4 Determined
$ grep de T
2 debug
3 determined
$ grep Determined T
4 Determined
$ grep determined T
3 determined
$ grep Debug T
1 Debug
$ grep debug T
2 debug
$ grep [D]ebug T # Why result is 2-nd line???
2 debug
$ grep [Dd]ebug T # Why result is only one 2-nd line???
2 debug
$ grep [Dd]e T
1 Debug
2 debug
3 determined
4 Determined
$ grep [d]e T
2 debug
3 determined
$ grep [d]ebug T
2 debug
$ grep "[D]ebug" T
1 Debug
$ grep "[Dd]ebug" T
1 Debug
2 debug
$ grep [\D]ebug T # Why result is 2-nd line???
2 debug
$ grep --version
grep (GNU grep) 2.16
As you can see, almost every grep call returns correct result, but $ grep [D]ebug T
, $ grep [Dd]ebug T
, $ grep [\D]ebug T
return wrong results. Why is this happening?
Best Answer
I'm guessing that you probably have a file or directory called
debug
in your current working directory:I commend you on this excellent illustration why you must always escape shell metacharacters.
Update to clarify what's going on: I'm assuming you, like I, are using an OS with a case-insensitive filesystem (e.g. a Mac). When you execute the command, your shell performs a number of expansions on it before actually executing
grep
. One of those is filename expansion in which square brackets provide alternations:[Dd]ebug
on a case-sensitive filesystem would expand to eitherDebug debug
,Debug
ordebug
depending on what files it could match. Since it only matched the filedebug
, your command became:If you remove that file and do
touch Debug
, you'll see the output of your command change because it will be interpolated asWithout the
debug
file in your directory, your shell tries to interpolate the brackets but fails without a match so it happens to pass the argument through unchanged.