Sunday, 18 August 2013

Unix command -grep

What is grep?

grep is a unix command used to find a  text(or pattern) in a file(s) or stream output. By default grep displays matching lines.
Syntax of grep command is
 grep options pattern filename(s)

Origin of grep :

grep comes from the ed command g/re/p (globally search a regular expression and print)and it works same as grep.ie. doing a global search with the regular expression and printing all matching lines. Both ed editor and grep command created by Ken Thompson

Let's start


Open terminal and execute following command from home directory(e.g. /home/dev001 )
grep PATH .profile
Sample Output
# set PATH so it includes user's private bin if it exists
    PATH="$HOME/bin:$PATH"
Explanation:
In .profile file above two lines  contain the PATH string. Hence two lines displayed in terminal as output.
Same output can be achieved by using following command
cat .profile | grep PATH
cat simply displays content of .profile in terminal(stream output) and grep command finds PATH string from that content.
For reference, sample .profile is also provided here
      1 # ~/.profile: executed by the command interpreter for login shells.
      2 # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
      3 # exists.
      4 # see /usr/share/doc/bash/examples/startup-files for examples.
      5 # the files are located in the bash-doc package.
      6
      7 # the default umask is set in /etc/profile; for setting the umask
      8 # for ssh logins, install and configure the libpam-umask package.
      9 #umask 022
     10
     11 # if running bash
     12 if [ -n "$BASH_VERSION" ]; then
     13     # include .bashrc if it exists
     14     if [ -f "$HOME/.bashrc" ]; then
     15         . "$HOME/.bashrc"
     16     fi
     17 fi
     18
     19 # set PATH so it includes user's private bin if it exists
     20 if [ -d "$HOME/bin" ] ; then
     21     PATH="$HOME/bin:$PATH"
     22 fi 
Can I search a text in multiple files or in a directory using grep?
 We can search in multiple files by  specifying file names. For searching in a directory use recursive option ( -r or -R ) and specify directory name
Say we are searching for INFO statement in LOGFILES directory which has three log files i.e Logfile1, Logfile2 and LogFile3
sample input command :
grep "INFO" Logfile1 Logfile2 LogFile3
grep -r "INFO"   LOGFILES
Looks good but grep command seems not working when I search for a string that contains whitespace. Say for example unmask 022(content of line 9). 
Input command :
  grep umask 022 .profile
Output:
grep: 022: No such file or directory
.profile:# the default umask is set in /etc/profile; for setting the umask
.profile:# for ssh logins, install and configure the libpam-umask package.
.profile:#umask 022
Explanation:
grep takes first parameter as input search string(pattern) and rest of the parameters are considered as  input files for searching. So in this case unmask string is searched in 022 and .profile files. As there is no file exists named 022 in home folder, first line comes as output. Rest of the result showing presence of unmask string in .profile file.
Solution :
Put double quotes in search input string.
grep "umask 022" .profile
Output:
#umask 022
Can I provide single quote instead of double quotes in pattern search string(i.e. 'umask 022' )?
single quote and double quotes in search string will act in same way if search string does not contain any special character(s).
For example    grep "umask 022" .profile and
grep 'umask 022' .profile will produce identical result But say we are searching for $HOME string in .profile file.
grep "$HOME" .profile provide no result where as
grep '$HOME' .profile gives following output
 if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
WHY?
If we run grep    "$HOME" .profile then first  $HOME(e.g. /home/dev001 ) is evaluated. So the command becomes 
grep    "/home/dev001" .profile
"/home/dev001" text is not present in .profile so grep result is blank .
On the other hand '$HOME' does not evaluate value of $HOME. So we get above results.
 Usage of single quote or Double quotes in search pattern basically depends on your requirement.   
We can use "\$HOME" instead of "$HOME"  as escape character "\" removes special meaning of "$".
It is not possible to provide exact string  for searching every time. How can I use grep in that scenario?
 Answer: You can use regular expression and also case insensitive search.
In next blog we will explore regular expression. 
Example:
 grep -i "bash" .profile
Output:
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
 I have huge log file and I am searching for "ERROR" occurence. Can I print line number in search result.
 Yes. use  grep -n "ERROR" <logfilename(s)>
I want to find number of "ERROR" occurrence in my application log file.
use  grep -c "ERROR" <logfilename(s)> to count search string occurrence in input file(s)
In .profile file I saw many comment lines started with #. Is it possible to search lines that does not have #?
 use grep -v "#" .profile 
Output:
if [ -n "$BASH_VERSION" ]; then
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

No comments:

Post a Comment