views:

529

answers:

4

So, I have a file called 'dummy' which contains the string:

"There is 100% packet loss at node 1".

I also have a small script that I want to use to grab the percentage from this file. The script is below.

result=`grep 'packet loss' dummy` |
awk '{  first=match($0,"[0-9]+%")
        last=match($0," packet loss")
        s=substr($0,first,last-first)
        print s}'

echo $result

I want the value of $result to basically be 100% in this case. But for some reason, it just prints out a blank string. Can anyone help me?

+2  A: 

Try

awk '{print $3}'

instead.

Steve Emmerson
So much simpler for the awk - but it doesn't deal with the shell scripting issue at the core of the problem. I gave you +1, but it would have been +0.7 if that was an option.
Jonathan Leffler
+1  A: 

You would need to put the closing backtick after the end of the awk command, but it's preferable to use $() instead:

result=$( grep 'packet loss' dummy |
awk '{  first=match($0,"[0-9]+%")
    last=match($0," packet loss")
    s=substr($0,first,last-first)
    print s}' )

echo $result

but you could just do:

result=$( grep 'packet loss' | grep -o "[0-9]\+%" )
Dennis Williamson
Good analysis - and you could use the simple awk script that Steve suggested instead of the non-standard '-o' option to grep.
Jonathan Leffler
Also the non-standard $( ) stuff. Some of us still use plain vanilla sh from decades ago.
janks
@janks: *Old* Bourne shells on *legacy* systems don't have `$()`, but it's not "non-standard" - it's specified in [POSIX](http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03) and many modern versions of `sh` (and other shells linked as `sh`) *do* have it. And there are [some reasons](http://mywiki.wooledge.org/BashFAQ/082) that it's preferred.
Dennis Williamson
Yeah, I didn't mean that it is not a standard feature of bash. I meant that bash is not a standard shell. It is not required to be present, and I've used relatively modern versions of relatively popular commercial unix variants, (ie, not legacy systems), that did not ship with it. So why target it when the plain-sh equivalent code is trivial?
janks
@janks: If you notice, I did not mention Bash or anything Bash-specific in my comment (except for one of the links) *or* my answer. And the stuff discussed in that link is not (in this case) Bash-specific (even though it's a Bash-related site). To repeat myself: `$()` is POSIX-standard.
Dennis Williamson
@DennisWilliamson: The POSIX standard for what? Not the bourne shell:`# /usr/bin/sh -c 'foo=$(grep root /etc/group)'` gets me a `/usr/bin/sh: syntax error at line 1: foo=$ unexpected`. Lest you suggest that I'm on a legacy system, this is Solaris 10. Only when I change `/usr/bin/sh` to `/usr/bin/bash` or `/usr/bin/ksh` does that construct not error out.
janks
@janks: It's not a [POSIX-standard](http://www.opengroup.org/onlinepubs/9699919799/) shell then.
Dennis Williamson
+2  A: 

the solution below can be used when you don't know where the percentage numbers are( and there's no need to use awk with greps)

$ results=$(awk '/packet loss/{for(i=1;i<=NF;i++)if($i~/[0-9]+%$/)print $i}' file)
$ echo $results
100%
ghostdog74
A: 

Here I'm assuming that the output lines you're interested in adhere strictly to your example, with the percentage value being the only variation.

With that assumption, you really don't need anything more complicated than:

awk '/packet loss/ { print $3 }' dummy

This quite literally means "print the 3rd field of any lines containing 'packet loss' in them". By default awk treats whitespace as field delimiters, which is perfect for you.

If you are doing more than simply printing the percentage, you could save the results to a shell variable using backticks, or redirect the output to a file. But your sample code simply echoes the percentages to stdout, and then exits. The one-liner does the exact same thing. No need for backticks or $() or any other shell machinations whatsoever.

NB: In my experience, piping the output of grep to awk is usually doing something that awk can do all by itself.

janks