5

I am writing a bash script; I execute a certain command and grep.

pfiles $1 2> /dev/null | grep name # $1 Process Id

The response will be something like:

sockname: AF_INET6 ::ffff:10.10.50.28  port: 22
peername: AF_INET6 ::ffff:10.16.6.150  port: 12295

The response can be no lines, 1 line, or 2 lines.
In case grep returns no lines (grep return code 1), I abort the script; if I get 1 line I invoke A() or B() if more than 1 line. grep's return code is 0 when the output is 1-2 lines.

grep has return value (0 or 1) and output.
How can I catch them both ? If I do something like:

OUTPUT=$(pfiles $1 2> /dev/null | grep peername)

Then variable OUTPUT will have the output (string); I also want the boolean value of grep execution.

  • I'm not sure if I understood the question. Do you need the output from grep at all? Do you need the return value? Would it be enough to just count the matchs, as per my answer below? – pfnuesel Jun 22 '17 at 15:21
  • I need the output and return code. $? Might do the job – ilansch Jun 22 '17 at 15:34
  • @ilansch I added another answer that should satisfy your requirements. – pfnuesel Jun 22 '17 at 21:21
  • "variable OUTPUT will have the output (string); I also want the boolean value of grep execution." Where this two values should be stored (boolean value and grep output)? In the OUTPUT variable both, each on its own line? Just interesting, what you wanted. – MiniMax Jun 25 '17 at 18:11
5

You can use

output=$(grep -c 'name' inputfile)

The variable output will then contain the number 0, 1, or 2. Then you can use an if statement to execute different things.

  • Why the downvote? – pfnuesel Jun 27 '17 at 14:24
1

If you need the result of grep, you can not use the -c flag as outlined in the other answer. What you can do, though, is running twice, once with -c flag to get the number of matches and one without -c flag, to see the matches. However, this can be very inefficient, depending on the size of your input file.

You can do something like this:

Content of input:

The first line is foo
I have a drink at the bar
The third line is foo again

Content of script:

#!/usr/bin/env bash

countMatches(){
    echo Searching for "${1}"
    result=$(grep "${1}" input)
    if [ $? -eq 1 ]; then
        echo No match found
        echo
        exit 1
    fi

    if [ $(echo "${result}" | wc -l) -eq 1 ]; then
        echo 1 match found:
        echo "${result}"
        echo
    else
        echo 2 matches found:
        echo "${result}"
        echo
    fi
}

countMatches foo
countMatches bar
countMatches baz

And here's the output when you invoke the script:

Searching for foo
2 matches found:
The first line is foo
The third line is foo again

Searching for bar
1 match found:
I have a drink at the bar

Searching for baz
No match found
1

This is fairly simple:

OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
grep_return_code=$?

If a $(…) command substitution is assigned to a variable, $? will get the return code from the last command in the $(…).  And, of course, you don’t need to refer to $? explicitly; you can do things like

if OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
then
    # the rest of the script
                ︙
fi

or

if ! OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
then
    exit
fi
# the rest of the script

This approach is useful in situations where the output of the command and its return code (a.k.a. exit status) are uncorrelated.  But, for grep, they are highly correlated: If it produced output, it succeeded.  If it didn’t produce output, it failed.  So why not just test the output ?

OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
if [ "$OUTPUT" ]
then
    # the rest of the script
                ︙
fi

or

OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
if [-z "$OUTPUT" ]
then
    exit
fi
# the rest of the script

P.S. You should always quote your shell variable references (e.g., "$1") unless you have a good reason not to, and you’re sure you know what you’re doing.

0

Try this code, I feel, it doing what you want.

  1. I put grep output to the OUTPUT variable
  2. I think, you don't need grep exit status as boolean value. It is 0 or 1, and it doesn't suit to your task. You need amount of lines - 0, 1, 2, etc. Therefore, count lines in the OUTPUT variable and put this number to the second variable - line_count. We will have two variables in the result. First with grep output, second with amount of lines.
  3. Then, check line_count in the case statement and do needed action.

Usage: ./switching_by_grep_result.sh your_file.txt

#!/bin/bash

# your code
OUTPUT=$(pfiles $1 2> /dev/null | grep name) # $1 Process Id

# count lines in the OUTPUT variable by using 'grep -c'
line_count=$(echo -n "$OUTPUT" | grep -c '^')

# checks lines count in here and invokes needed script or exit.
# if 0 lines - exit
# if 1 lines - invoke A
# if any other number of lines - invoke B
case $line_count in  
    0) echo 'exit'
    ;;  
    1) echo 'A() script invoking here'
    ;;  
    *) echo 'B() script invoking here'
    ;;  
esac

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.