1

I've recently noticed this message from grep

"grep: warning: GREP_OPTIONS is deprecated; please use an alias or script"

I receive this warning because --color=always is defined in my .bashrc file. AFAIK alias is impractical, because I want this to work on a pipe. For example,

echo "a b c" |grep b

should highlight b. Since an alias will not work, the other option presented is to make a script. But how do I make a script accept input from a pipe? In this case, I want the script append --color=always.

EDIT: An alias does work after all... and so does making a script. I have no idea what I was doing wrong with the alias method. However, in making a script be sure to include $1 for input parameter.

For anyone else wanting to know how to pipe to your own script, in this example it worked for me by doing the following:

first make the script in a location in the path so its executable, e.g.

# ~/.bin/testgrep
grep --color=always $1

Now make the script executable, e.g.

chmod +x ~/.bin/testgrep

Now it should work!

  • What do you mean "an alias will not work"?  But also, what part of making a script accept input from a pipe is causing you difficulty? – G-Man May 6 '15 at 2:38
  • An alias does work! Since it was in .bashrc I needed to reload the terminal. Also, I was having difficulty because in the script I forgot to include the $1 for the input parameter – Caezec May 6 '15 at 6:45
  • Never put --color=always in GREP_OPTIONS. This breaks many scripts that expect the output of grep to be lines from the file, without extra stuff. echo "a b c" |grep --color=auto b does highlight b. – Gilles May 6 '15 at 21:59
  • an alias does work in a pipe....unless you are using something like xargs grep. that fails because xargs forks grep by itself and does not use shell aliases. – cas Oct 25 '15 at 4:31
-1

grep (i.e., /bin/grep) will read from standard input if it is invoked with no filename arguments.  So it is simple to write a script that runs grep with input from standard input — just invoke grep with no filename arguments.  But grep must be given (at least) one PATTERN argument (or equivalent).  An extremely inflexible way to do that, which is unlikely to be very useful in real life, is to hard-code a search string (pattern) into your grep script; e.g.,

#!/bin/sh
grep --color=always cat

which could be used in the context

ps | mygrep

and probably not much else.  A slightly more flexible script might use an environment variable as the search string:

#!/bin/sh
grep --color=always $USER

which could be used in the context

ps -ef | mygrep

and probably not much else.  The only reasonable, realistic, robust solution is to allow the user of the script to supply a search string as a command-line argument:

#!/bin/sh
grep --color=always $1

which could be used in the context

dmesg | mygrep TCP

and might actually be fairly useful.

Well, maybe I should say somewhat useful.  This breaks down fairly quickly, as you might need multiple arguments to specify the search parameters:

mygrep -i tcp                   Case-insensitive search; find tcp, TCP, Tcp, etc.
mygrep -v bash                  Find everything except bash.
mygrep -e cat -e dog            Find every line that contains cat or dog.
mygrep -f wordlist              Search strings are in a file.

So the second draft of our script might be:

#!/bin/sh
grep --color=always $1 $2 $3 $4 $5 $6 $7 $8 $9

which could handle any of the above examples.  As an extra bonus, this doesn’t need to be used to read the standard input; we can say

mygrep -i path .bashrc

and it will run

grep --color=always -i path .bashrc

But we’re not done yet!  Consider

mygrep  "cat food"  "shopping list.txt"

which will run

grep --color=always cat food shopping list.txt

which will (try to) search for cat in three files: food, shopping, and list.txt.  OK, we can handle that by saying

#!/bin/sh
grep --color=always "$1" "$2"

but

#!/bin/sh
grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"

isn’t a good answer; it will turn

mygrep  "cat food"  "shopping list.txt"

into

grep --color=always  "cat food"  "shopping list.txt"  ""  ""  ""  ""  ""  "" ""

which will do what you want, but will also issue seven error messages.

So, what to do, what to do?  Oh, wait; I have a sledgehammer in my closet:

#!/bin/sh
if [ "$1" = "" ]
then
    printf "%s\n" "error: mygrep must be run with at least one argument."
elif [ "$2" = "" ]
then
    grep --color=always "$1"
elif [ "$3" = "" ]
then
    grep --color=always "$1" "$2"
elif [ "$4" = "" ]
then
    grep --color=always "$1" "$2" "$3"
elif [ "$5" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4"
elif [ "$6" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5"
elif [ "$7" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6"
elif [ "$8" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7"
elif [ "$9" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8"
else
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"
fi

Right.

  1. That’s laughably impractical.
  2. Even that fails for

    mygrep  -e cat  -e dog  -e fish  file1  file2  file3  file4
    

    because it has more than nine arguments!  And, while this situation may seem unlikely, the same problem occurs with

    mygrep  bird  *
    

    if there are more than eight (non-hidden) files in the current directory.

So, what to do, what to do?

TL;DR

If you look in bash(1) under Special Parameters, you’ll see that $@ expands to the list of positional parameters, starting from one.  When the expansion occurs within double quotes, each parameter expands to a separate word.  That is, "$@" is equivalent to "$1""$2" … (as implemented in the long script, above, but not limited to the first nine).  So, the way to write a script to wrap (i.e., act as a front-end for) some command, acting like an alias, is

#!/bin/sh
grep --color=always "$@"
2

An alias will work. I have grep aliased to grep --color=auto:

% which grep
grep: aliased to grep --color=auto

And piping to grep has the behavior you desire:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.