How to append fields from one row on to the end of the preceding row - the awk one isn't completely tested yet - this gives the output the other way round...
Try...
paste -d" " - - <> outfile
Or...
awk -v RS="" '{$1=$1};1' infile > outfile
If anyone know's how to improve this please let me know! ...Also I'm not sure why the '-v' variable declaration is required?
Thursday, 21 August 2008
Tuesday, 19 August 2008
awk: numerical addition and grouping
The following script performs a count of the numerical data in a column ($3) and then groups that data by $1.
awk -F'#' 'BEGIN {}
{
sum[$1] += $3
} END {
for ( i in sum ) print i" : "sum[i]
}' $1
Notice how I'm making the value of the array sum[$1] the addition of the numerical values found at field three ($3):
sum[$1] += $3
Essentially evertime awk comes across a $1 value it adds the value of $3 to the array index of $1.
awk -F'#' 'BEGIN {}
{
sum[$1] += $3
} END {
for ( i in sum ) print i" : "sum[i]
}' $1
Notice how I'm making the value of the array sum[$1] the addition of the numerical values found at field three ($3):
sum[$1] += $3
Essentially evertime awk comes across a $1 value it adds the value of $3 to the array index of $1.
awk: printing from a specified field onwards
OK, this is way to complicated when a simple substr() on $0 will suffice but I like it!
awk '{for(i=1;i<4;i++)$i="";sub(/^ */,"");print}' error.txt | sort -u
Notice that it's piped into a sort because awk doesn't have it's own sort command.
All this command is doing is printing everything after field four.
Below is a modification of the above command that prints only the unique lines (based on all fields after field 4):
awk '{for(i=1;i<4;i++)$i=""; sub(/^ */,""); err[$0] = $0 } END { for ( u in err ) print err[u] }'
Notice that $0 is the modified $0 without fields one thru 4.
awk '{for(i=1;i<4;i++)$i="";sub(/^ */,"");print}' error.txt | sort -u
Notice that it's piped into a sort because awk doesn't have it's own sort command.
All this command is doing is printing everything after field four.
Below is a modification of the above command that prints only the unique lines (based on all fields after field 4):
awk '{for(i=1;i<4;i++)$i=""; sub(/^ */,""); err[$0] = $0 } END { for ( u in err ) print err[u] }'
Notice that $0 is the modified $0 without fields one thru 4.
awk: working out thresholds
The following code was written to work out threshold breaches - the input is standard sar data.
The interesting part is the alert.awk script at the bottom.
The shell script wrapper defines the following variables that are passed to the awk code:
${i} - is the system name
amb - is the amber alert threshold value
count - is the amount of times this threshold occurs
count=`grep ${i} alert_cpu.conf|awk -F, '{ print $4 }'`
amb=`grep ${i} alert_cpu.conf|awk -F, '{ print $2 }'`
awk -v val=${amb} -v count=${count} -f alert.awk cpu2.dat >>detailed_alert_report_${DAY}.txt
alert.awk script:
$(NF)>val {c++; o=o $0 ORS; next}
c>count {printf "%s",o; C++}
{c=0; o=""}
END {if (c>count) {printf "%s",o; C++} print C+0}
The interesting part is the alert.awk script at the bottom.
The shell script wrapper defines the following variables that are passed to the awk code:
${i} - is the system name
amb - is the amber alert threshold value
count - is the amount of times this threshold occurs
count=`grep ${i} alert_cpu.conf|awk -F, '{ print $4 }'`
amb=`grep ${i} alert_cpu.conf|awk -F, '{ print $2 }'`
awk -v val=${amb} -v count=${count} -f alert.awk cpu2.dat >>detailed_alert_report_${DAY}.txt
alert.awk script:
$(NF)>val {c++; o=o $0 ORS; next}
c>count {printf "%s",o; C++}
{c=0; o=""}
END {if (c>count) {printf "%s",o; C++} print C+0}
awk: putting blank lines between non-alike lines
I had some output that was really difficult to read and so I wanted to split the output into blocks that were similar - where they had the same $1 value. This fab little awk command puts a blank line between each block (multiple lines) where $1 changes.
(don't ask me how it works tho because I got it off a really nice chap at www.unix.com)
awk 'x[$1]++||$0=NR==1?$0:RS $0' test2
If anyone can explain it to me please feel free! :)
(don't ask me how it works tho because I got it off a really nice chap at www.unix.com)
awk 'x[$1]++||$0=NR==1?$0:RS $0' test2
If anyone can explain it to me please feel free! :)
awk: handy one-liners
This is a great resource for simple command line awk:
http://student.northpark.edu/pemente/awk/awk1line.txt
http://student.northpark.edu/pemente/awk/awk1line.txt
awk: getting data based on previous lines
Here's a little awk script that I wrote to collect data from a field where it's heading is in the line above (both are at $4 - space separated). The input file looks like this:
ARTMGA01_usage_07Mar07-1500:# CPU SUMMARY
ARTMGA01_usage_07Mar07-1500-# USER SYS IDLE WAIT INTR SYSC CS RUNQ AVG5 AVG30 AVG60 FORK VFORK
ARTMGA01_usage_07Mar07-1500- 4 6 90 0 1002 7214 9093 0 0.21 0.18 0.17 2.73 0.59
ARTMGA01_usage_07Mar07-1500:# CPU SUMMARY
ARTMGA01_usage_07Mar07-1500-# USER SYS IDLE WAIT INTR SYSC CS RUNQ AVG5 AVG30 AVG60 FORK VFORK
ARTMGA01_usage_07Mar07-1500- 4 9 87 0 905 7552 8530 1 0.32 0.21 0.18 2.20 0.40
ARTMGA01_usage_07Mar07-2100:# CPU SUMMARY
ARTMGA01_usage_07Mar07-2100-# USER SYS IDLE WAIT INTR SYSC CS RUNQ AVG5 AVG30 AVG60 FORK VFORK
ARTMGA01_usage_07Mar07-2100- 4 5 90 0 1052 7777 9492 0 0.19 0.18 0.18 2.65 0.59
Here's the actual code:
BEGIN {}
{
if ($4 ~ /IDLE/) {
getline
idleval = idleval + $4
count++
}
}
END {
print "Total: " idleval
print "Count: " count
print "Average: " idleval / count
}
There's nothing new in this code that we haven't already covered but it's a good 'simple' example of how awk's getline function can be used. We essentially do a search for 'IDLE' then skip to the next line with getline and collect the value at $4 (field four). The 'count' value is incremented for every line that matches 'IDLE' which is how we can then work out the average:
print "Average: " idleval / count
('idleval' divided by 'count').
ARTMGA01_usage_07Mar07-1500:# CPU SUMMARY
ARTMGA01_usage_07Mar07-1500-# USER SYS IDLE WAIT INTR SYSC CS RUNQ AVG5 AVG30 AVG60 FORK VFORK
ARTMGA01_usage_07Mar07-1500- 4 6 90 0 1002 7214 9093 0 0.21 0.18 0.17 2.73 0.59
ARTMGA01_usage_07Mar07-1500:# CPU SUMMARY
ARTMGA01_usage_07Mar07-1500-# USER SYS IDLE WAIT INTR SYSC CS RUNQ AVG5 AVG30 AVG60 FORK VFORK
ARTMGA01_usage_07Mar07-1500- 4 9 87 0 905 7552 8530 1 0.32 0.21 0.18 2.20 0.40
ARTMGA01_usage_07Mar07-2100:# CPU SUMMARY
ARTMGA01_usage_07Mar07-2100-# USER SYS IDLE WAIT INTR SYSC CS RUNQ AVG5 AVG30 AVG60 FORK VFORK
ARTMGA01_usage_07Mar07-2100- 4 5 90 0 1052 7777 9492 0 0.19 0.18 0.18 2.65 0.59
Here's the actual code:
BEGIN {}
{
if ($4 ~ /IDLE/) {
getline
idleval = idleval + $4
count++
}
}
END {
print "Total: " idleval
print "Count: " count
print "Average: " idleval / count
}
There's nothing new in this code that we haven't already covered but it's a good 'simple' example of how awk's getline function can be used. We essentially do a search for 'IDLE' then skip to the next line with getline and collect the value at $4 (field four). The 'count' value is incremented for every line that matches 'IDLE' which is how we can then work out the average:
print "Average: " idleval / count
('idleval' divided by 'count').
Subscribe to:
Posts (Atom)