Scripts – Using awk Command in Perl Script

awkperlscripts

Can somebody suggest how to use piping of commands in a perl script?
Specifically commands that involve calling awk?

I'm trying to create a perl script that will read disk usage using df -H and return the second-last row of output, which shows the %use.
Entering the command directly in the terminal returns the desired output.

df -H | awk '{print $(NF-3)}'

This command is returning the right results. But when using the same command in the reverse tick utility, the perl script throws a lot of errors.

$thirdlast=`df -H | awk '{print $(NF-3)}'`;
print $thirdlast;

Why does the same command not run in the script? Is there any other way to return the required results?

Best Answer

The main problem is that the $ is important to perl. When you use it in a system command, you need to escape it:

$thirdlast=`df -H | awk '{print \$(NF-3)}'`;
print $thirdlast;

Otherwise, perl will try to expand $(NF-3) as a perl variable. The variable $( is the perl process's real GID:

$(

The real gid of this process. If you are on a machine that supports membership in multiple groups simultaneously, gives a space separated list of groups you are in.

The variable $) is the process's effective GID:

So, $(NF-3) evaluates to list of groups you are a member of NF-3). For example, on my system, that is:

$ perl -le 'print "$(NF-3)"'
1001 27 29 111 112 1001NF-3)

The next problem is that your awk call is wrong. The % use is $(NF-1), not $(NF-3). So, what you wanted is:

$thirdlast=`df -H | awk '{print \$(NF-1)}'`;

Or, to only print percentages above a certain threshold, for example 90:

$thirdlast=`df -H | awk '(\$(NF-1)>90){print \$(NF-1)}'`;

In any case, you could just process the output of df in Perl itself:

$thirdlast=`df -H`;
@matches=($thirdlast=~/(\S+%)/g);
print "@matches\n";

Or

@matches=(`df -H`=~/(\S+%)/g);
print "@matches\n";

And to set a threshold:

@matches=(`df -H`=~/(\S+%)/g);
@above90=grep {$_>90} @matches;
print "@above90\n";

Or, more directly:

@matches=grep {$_ >90} (`df -H`=~/(\S+%)/g);
print "@matches\n";

The @array=($variable=~/foo/g) will save all matches of the regular expression foo in the variable $variable into the array @matches. That will have the same result as parsing the df with awk.

Related Question