Print certain lines based on condition

Hi All,
I have following listing

[172.29.38.40]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/hd2           4.00      0.31   93    63080    43 /usr

[172.29.38.41]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on

[172.29.38.42]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on

[172.29.38.43]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/appvglv05     14.00      0.59   96      316     1 /OUTBOUND

[172.29.38.45]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/hd2           4.00      0.29   93    63070    44 /usr
/dev/hd3          10.00      0.90   91    24577    10 /tmp

As you can see I use the script to capture those filesystem more than 90% and output to a logfile. But I just want those only server that exceeded to display out. Pls share thanks.

The following awk script seems to do what you want:

awk '
function printlist(     i) {
        for(i = 1; i <= c; i++)
                printf("%s\n", l)
        print "" 
}
/^[[]/ {if(c > 2) printlist()
        c = 0 
}
/./ {   l[++c] = $0
}
END {   if(c > 2) printlist()
}' listing

If you are running this on a Solaris/SunOS system, use /usr/xpg4/bin/awk , /usr/xpg6/bin/awk , or nawk instead of awk .

With your sample input, this produces the following output:

[172.29.38.40]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/hd2           4.00      0.31   93    63080    43 /usr

[172.29.38.43]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/appvglv05     14.00      0.59   96      316     1 /OUTBOUND

[172.29.38.45]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/hd2           4.00      0.29   93    63070    44 /usr
/dev/hd3          10.00      0.90   91    24577    10 /tmp

awesome. Very powerful awk script command. Thanks for your sharing.

---------- Post updated at 02:39 AM ---------- Previous update was at 12:51 AM ----------

Thanks Don for your kind sharing. Btw, can you explain a bit on the highlighted part that I not understand.

awk '
function printlist(     i) {
        for(i = 1; i <= c; i++)
                printf("%s\n", l)
        print "" 
}
/^[[]/ {if(c > 2) printlist()   <<= if found first character is [ and c > 2 initialize the var c
        c = 0 
}
/./ {   l[++c] = $0              <<= can elaborate more on this?
}
END {   if(c > 2) printlist()   
}' listing

Thank You Very Much.

Alternatively:

awk 'NF>10' RS= ORS='\n\n' file

Hi Scrutinizer, the script you posted it print out all rows. The one Don did, yes I had tested it is working. Thanks.

It works fine for me. Again it show the power of record selector.

awk 'NF>10' RS= ORS='\n\n' file
[172.29.38.40]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/hd2           4.00      0.31   93    63080    43 /usr

[172.29.38.43]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/appvglv05     14.00      0.59   96      316     1 /OUTBOUND

[172.29.38.45]
Filesystem    GB blocks      Free Used    Iused Iused Mounted on
/dev/hd2           4.00      0.29   93    63070    44 /usr
/dev/hd3          10.00      0.90   91    24577    10 /tmp

@ckwan
What is your output of:

awk '{$1=$1}1' RS= ORS='\n\n' file

@ckwan
My suggestion would only work if the format is like in your sample (10 fields in the header) and if there are no additional space characters on empty lines (i.e. two consecutive newlines), which is usually the case with output from utilities. If that is not the case then a solution like Don's would work more reliably...

Yes this is working. I guess the RS=[space], without space it will have not print out correctly. Thanks everyone for your sharing. Thanks Scrutinizer.

---------- Post updated at 04:50 AM ---------- Previous update was at 04:32 AM ----------

Hi Guys, any idea which site I can find information about the adv awk script I can pick up ?

Hi ckwan,
Here is a version of the script with comments added. Let me know if something is still not clear.

awk '
# Define a function named printlist()
function printlist(     i) { # It has a local variable (i).
        for(i = 1; i <= c; i++) # For every line in the array l[], 
                printf("%s\n", l) # print that line.
        print "" # Then print an empty line as a separator.
}
# If the 1st character on a line is '[',
/^[[]/ {if(c > 2) printlist() # if we have more than two lines saved, print the saved lines.
        c = 0 # Clear the number of saved lines no matter how many lines were saved before.
}
# If the input line is not empty,
/./ {   l[++c] = $0 # increment the number of saved lines (c) and save the current line.
}
# When we hit end-of-file,
END {   if(c > 2) printlist()  # if we have more than two lines saved, print the saved lines.
}' listing # Our input file is named "listing"

For any Linux or UNIX system utility, you should be able to find out how it works by issuing the command:

man 1 utility_name

If that doesn't work for you, try looking at the "Man Pages" section of this forum. The POSIX section gives you the (hopefully) portable subset of options for a utility that should work on most systems. For awk, that would be the POSIX awk utility description.

I avoided the simpler solution (suggested by Scrutinizer and Jotne) using RS= because although setting the input record separator to an empty string works on some implementations of awk; it is not portable. The standards only specify the behavior of an awk program if RS is defined to be a single character other than the NULL character.

Hi Don,

I don't think that is correct:

awk: Variables and Special Variables

1 Like

Thanks Scrutinizer,
I stand corrected. The behavior is defined when RS is an empty string.

The behavior is unspecified when FS is an empty string. (And, it is fairly common to find scripts in these forums that assume that FS= will make every character on a line be a separate field. I confused this issue with FS when I was talking about RS. I obviously need to get some sleep.)

Thanks for spending time for resolving the issue. All inputs are very appreciated. Thanks again.