If you go the command:
Code:
grep "foo bar" input_file
The shell processes the quotes when it handles the command. In this case it means the pattern is:
including the space. Grep therefore receives this list of arguments in argv (excluding argv[0] which is the program name):
- foo bar
- input_file
The thing to note is that the shell strips out the quotes because it is using the shell is interpretting them. If you want to prevent the shell from interpretting the quotes, you can do one of many things, depending on what you want to happen. Firstly, you can
escape each quote:
Code:
grep \"foo bar\" input_file
This might not be what you want in this case, because the input parameter list will be:
- "foo
- bar"
- input_file
so the search pattern would be foo" and the intput files would be bar" and input_file.
You can also use a double quote within double quotes, by escaping it:
Code:
grep "foo\"bar" input_file
This might not be what you want in this case, because the input parameter list will be:
- foo"bar
- input_file
You can also put double quotes within single quotes. Single quotes prevent anything from their midst from being interpretted by the shell:
Code:
grep 'foo"bar' input_file
argv would look like this:
- foo"bar
- input_file
The single quotes are also useful for you because you have as part of your patter the $ character followed by a word. If you did not quote the string, or if you used double quotes, the shell would interpret $studentname to mean "the value of the shell variable studentname". This is almost certainly not what you want. Consider this:
Code:
grep \".$studentname.\".tablename input_file
Here we have escapes the quotes, so they will make it through to the grep argv list, but the shell will replace the $studentname with the value of that variable in the shell, which is probably not set. So grep will get this argument list:
- "..".tablename
- input_file
To prevent both quote expansion and variable expansion, just whack the whole lot in single quotes, like this:
Code:
grep '".$studentname.".tablename' input_file
Here's what grep sees...
- ".$studentname.".tablename
- input_file
But wait, this is not what you
really want... grep interprets the first argument as a
regular expression pattern, and in this both . and $ have special meanings. If you want to find literal strings instead of searching for regular expressions, you can use fgrep instead. You might have to know about the regular expressions though because you want to do a replace, and probably you will move on to using
sed for that, which will expect to search and replace using regular expressions...
You can go an read a regular expression tutorial if you want to know exactly why, but here I will just say that you need to prefix the $ and the . characters with a backslash to make grep treat them like a litern character, and not as a special pattern:
Code:
grep '"\.\$studentname\."\.tablename' input_file
Here's what grep sees...
- "\.\$studentname\."\.tablename
- input_file
Here's a handy hint: If you want to check to see what grep would see after quote processing of the shell, just pass that string to the echo command and have a look at the output. e.g:
Code:
% echo '"\.\$studentname\."\.tablename'
"\.\$studentname\."\.tablename