A colleague of the company, when writing the shell, raised such a requirement that the SAR output would idle the column output and would require a different platform. In Linux, the $NF column is printed through awk ilde column, assuming that under other platforms, such as FreeBSD under the Idle column is $ (NF-1) column, Hp-unix under the column (just assume, do not directly to the table), what should the shell write?
Train of thought: first thought to find the column number that matches the idle string through awk, and then print the column. But after pondering the afternoon did not realize, and then thought by converting columns to rows, and then grep idle line. The latter kind of idea passes the test to realize.
One, Python implementation (column career change idea)
This is the fastest way to write a method, the principle is a column change, and then judge a keyword in the line (that is, before the conversion of the column), in the print out.
The test files are as follows:
[Root@361way ~]# cat/tmp/test.file
cpu %user %nice %system %iowait %steal %idle
all 0.50 0.00 0.50 0.00 0.00 98.99
all 0.50 0.00 0.00 0.50 0.00 99.00
all 0.50 0.00 0.25 0.25 0.00 99.00
Python code is as follows:
With open (' Test.file ') as F:
Lis = [X.split () for x in F]
For x in Zip (*lis):
If '%idle ' in x:
Print X
First the lines are taken out, and by the space cut into various elements, LIS results are [(a,b), (C,D)] such a format. The column is then combined with a zip combination. The last is judgment. It's simple, right?
Second, AWK+GREP implementation (column change)
The code for awk to implement row and column conversions is as follows:
# awk ' {for (i=1;i<=nf;i++) a[nr,i]= $i}end{for (j=1;j<=nf;j++) for (k=1;k<=nr;k++) printf K==nr?a[k,j] RS:a[k,j ] FS} ' test.file
It doesn't look like it's a pain in the egg, even the ternary operator is used. Simplified under:
[Root@361way tmp]# awk ' {for (i=0;++i<=nf;) a[i]=a[i]?a[i] FS $i: $i}end{for (i=0;i++<nf;) print A[i]} ' Test.file
CPU all All
%user 0.50 0.50 0.50
%nice 0.00 0.00 0.00
%system 0.50 0.00 0.25
%iowait 0.00 0.50 0.25
%steal 0.00 0.00 0.00
%idle 98.99 99.00 99.00
The last code implemented is:
awk ' {for (i=0;++i<=nf;) a[i]=a[i]?a[i] FS $i: $i}end{for (i=0;i++<nf;) print A[i]} ' test.file |grep idle
Looks good, but the feeling is still not satisfied, or want to achieve through direct column matching.
Three, direct column matching
When the problem is thrown out of the group, it is true that Daniel has come up with the direct awk match the column number of the idle string, and then print the method of the column. Specifically as follows:
Method 1:for Loop
[Root@361way tmp]# awk ' nr==1{for (i=1;i<=nf;i++) if ($i ~/idle/) n=i}nr>1{print $n} ' Test.file
98.99
99.00
99.00
Method 2:when Loop, array fetch
[Root@361way tmp]# awk ' Nr==1{while (n++<nf) a[$n]=n} {if (nr>1) print $a ['%idle ']} ' test.file
98.99
99.00
99.00
When the data is the most large, method 1 here is relatively more efficient.
Method 3:python Implement
Python has no advantage in simple text streaming, I write a code that feels pretty long, but it's easy to understand--the principle or row-by-line code is as follows:
Import Linecache
Theline = Linecache.getline (R '/tmp/sar.txt ', 1)
Nums = Range (len (Theline.split ()))
Titles = Theline.split ()
For num in nums:
If ' idle ' in Titles[num]:
Print num
With open ('/tmp/sar.txt ') as F:
For row in F:
Print row.split () [num]
Finally: Here is a Perl version of the tool Csvgrep, you can refer to the tool example "Csvgrep ' @header $NR = = 1; ${name} ' contacts.csv ' usage. There is also a need to convert a row to a column in the actual application, or to change a column to row output, which makes it easy to value. Here is a convenient code to convert a column to a row, such as converting the last column to a row:
awk ' {printf '%s ', $NF} ' file