5

Suppose I have two files which look as follows:

$ cat search_file.txt
This line contains kwd1.
This line contains kwd2.
This line contains no match.
This line contains no match.
This line contains kwd5.
$ cat search_kwd.sh
grep kwd1 search_file.txt
grep kwd2 search_file.txt
grep kwd3 search_file.txt
grep kwd4 search_file.txt
grep kwd5 search_file.txt

When I run search_kwd.sh, I get:

$ sh search_kwd.sh
This line contains kwd1.
This line contains kwd2.
This line contains kwd5.

I want to print a string whenever grep does not get a match. The output would look like:

$ sh search_kwd.sh
This line contains kwd1.
This line contains kwd2.
string
string
This line contains kwd5.

How do I go about doing this in bash?

14

grep exits with non-zero code when nothing found.

From man grep:

Normally the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred.

So you can use:

grep kwd3 search_file.txt || echo "string"
  • 1
    +1 for the idiomatic use of ||; I was about to suggest if which does the same thing in a clunkier and more unwieldy manner. – Draconis Apr 29 at 15:54
  • This only tests for one of the examples, not all of them. – Monty Harder Apr 29 at 17:55
0

To expand on @RoVo's answer, you can use a for loop to iterate over all your queries:

for term in "kwd1" "kwd2" "kwd3" "kwd4" "kwd5"; do
    grep "$term" search_file.txt || echo "string"`
done
0

As the requested output seems to have one line of output for each line of input, where the line is just copied if it matches and is replaced if it doesn't, there are better ways to do this than reading the file 5 times and printing out the lines in the order they are found in the search_kwd.sh file rather than the input file.

Instead you should process the input file 1 line at a time. There are lots of tools that can do this. For example

#!/bin/sh
sed -e '/kwd1/{p;d}
        /kwd2/{p;d}
        /kwd3/{p;d}
        /kwd4/{p;d}
        /kwd5/{p;d}
        s/.*/string/' search_file.txt

which says for each of the matching kewwords print out the line, then discard it and move onto the next line. If it gets through all the keywords and none match then change the line to string (and then implicitly print it).

You could use awk with something like this

 #!/bin/sh
 awk '{ if (/kwd1|kwd2|kwd3|kwd4|kwd5/) { print } else {print "string" }}' search+file.txt

You could have a pure shell implementation

 #!/bin/sh
 while read -r line
 do
     case "$line" in
     (*"kwd1"*|*"kwd2"*|*"kwd3"*|*"kwd4"*|*"kwd5"*) printf '%s\n' "$line" ;;
     (*) printf '%s\n' "string" ;;
     esac
 done < search_file.txt

You could use perl, ruby, python, as well.

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.