Hallo, Am Tue, 20 Dec 2005, Steffen Dettmer schrieb:
* David Haller wrote on Tue, Dec 20, 2005 at 03:44 +0100:
==== awk 'NR == 1 || /max_kb_per_request|multcount/ { print $0"\t", n ? n : "device"; } /^name/ { n=gensub(".*/(hd.)/.*", "\\1", 0, FILENAME); }' /proc/ide/hd?/settings ====
Noch Fragen?
Ja:
awk: cmd. line:5: (FILENAME=/proc/ide/hda/settings FNR=1) warning: gensub: 3rd argument of 0 treated as 1
Was will mir AWK damit sagen?
==== man gawk [umformatiert] ==== gensub(r, s, h [, t]) If h is a string beginning with g or G, then replace all matches of r with s. Otherwise, h is a number indicating which match of r to replace. ==== Bei mir funktioniert das klaglos. Allerdings ist mein gawk auch schon ein wenig aelter (3.0.4). gensub ist aber sowieso eine GNU Extension. Es sollte also: n = gensub(".*/(hd.)/.*", "\\1", 1, FILENAME); sein. Tut mir leid.
<btw> In Perl:
perl -ane ' /max_kb_per_request|multcount/ && printf "%20s %10s %s\n", $F[0], $F[1], [split("/", $ARGV)]->[3]; ' /proc/ide/hd?/settings
Schick! Ich sollte z.B. perldoc perlrun doch mal komplett lesen, der Schalter '-a' war mit bisher unbekannt ;) Ich wuerde allerdings vermutlich '(split(...))[3]' statt '[split(...)]->[3]' verwenden. Naja, ist wohl egal, ob man sich nun ne Referenz auf eine anonyme Liste oder direkt die anonyme Liste nimmt und dann deren 3tes Feld holt... Und ausserdem auch eher so, wie es -MO=Deparse ausgibt: LINE: while (defined($_ = <ARGV>)) { our(@F) = split(" ", $_, 0); printf "%20s %10s %s\n", $F[0], $F[1], [split(m[/], $ARGV, 0)]->[3] if /max_kb_per_request|multcount/; } (Zeilenlaenge von mir gekuerzt), also das "printf ... if .... Witzig finde ich aber, dass beim split das "/" zu 'm[/]' wird, aber das matching beim if nicht zu if 'm/.../'... So, das mit den Listen/-refs hat mich jetzt doch interessiert: ==== anon-list.pl ==== #!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); my $res; my $hd = "/proc/ide/hdc/settings"; ### string fuer's split my $iters = 27; ### Anzahl Zeilen in /proc/ide/hdc/settings sub anon_listref { for( 1 .. $iters ) { $res = [split(m[/], $hd)]->[3]; } } sub anon_list { for( 1 .. $iters ) { $res = (split(m[/], $hd))[3]; } } cmpthese( -1, { anon_listref => \&anon_listref, anon_list => \&anon_list } ); ==== $ perl anon-list.pl Rate anon_listref anon_list anon_listref 1793/s -- -33% anon_list 2669/s 49% -- Haette nicht gedacht, dass das so ein Unterschied ist. Endlich hab ich mal "intuitiv" die schnellere Version genommen ;)
(braucht man nicht sed, awk, ... lernen sondern nur Perl - so man es hat)
Och, ich verwende je nach Aufgabe bash, grep, ed, sed, awk oder perl... Ggfs. auch C oder C++. Ruby und Python will ich mir irgendwann mal anschauen. Mein laengstes awk-script ist z.B. $ sed -n '1,/#\{68\}/{/^#/d;p;}' ~/bin/headmidtail | wc -l 162 Zeilen lang (reiner Code, fast ohne Kommentare[1] und den code aus '$prefix/share/awk/getopt.awk'[2]). Wird ein shell, sed, oder awk-script laenger als eben ca. 100 Zeilen und/oder laeuft es laenger als ca. 10s tendiere ich stark zu perl. Bei kurzen Scripten usw. tendiere ich gegen perl, weil das doch relativ langsam startet, speziell wenn man ein paar (groessere) Module verwendet... Fuer "Kurzkram" der haeufig gestartet wird sind die anderen Programme sinnvoller, d.h. wenn ein grep, sed, awk reicht, dann nehm ich das. BTW: grep kann AFAIK nix, was sed nicht kann und sed kann AFAIK nix, was (g)awk nicht kann. Folgerung: Sobald ein 'sed' auf einer Zeile (Pipe-Kette) auftaucht ist grep ersetzbar, und beide durch 'gawk'. Bsp: grep 'foo' bar gleich sed -n '/foo/p' bar gleich awk '/foo/' bar gleich perl -ne 'print if /foo/;' bar Man kann auch, gewissermassen, mit der bash "greppen": while read l; do test "x${l//*foo*/XXX}" = "xXXX" && echo "$l"; done < bar dabei darf aber in 'bar' aber keine Zeile mit nur XXX enthalten sein. Das laeuft zwar rein in der bash ist aber trotzdem langsamer als die grep, sed awk und sogar die perl-Variante (zumindest wenn perl schon im Plattencache ist, aber bei der bash kann man da ja auch von ausgehen). Die Regular Expression (RE) Varianten unterscheiden sich aber: grep und sed verwenden Basic RE, egrep/grep -E und awk verwenden Extended RE (siehe 'man 7 regex') und perl seine eigenen (siehe perldoc perlre, nochmals maechtiger als ERE). Und perl ist nicht ganz eine Obermenge von awk, genauer gesagt, aus 'perldoc perlvar': Remember: the value of $/ is a string, not a regex. awk has to be better for something. :-) d.h. ein 'awk -F "REGEX"' kann man in perl nur (umstaendlich) nachbauen. Mir jedenfalls macht es Spass bash, sed, awk und perl usw. zu kennen / koennen und mir je nach Aufgabe das "Richtige Tool"[tm] herauszusuchen, gemaess dem Motto: "Know thy tools!" und entgegen der (rausgesuchten) sig. Achso: nix gegen perl, ich mag perl sehr, aber es ist nicht immer das richtige Werkzeug. HTH & HAND, -dnh PS: schon mal die perlsh angeschaut? [1] es gibt ein paar (3 Zeilen oder so) direkt im code, wo sie sinnvoll sind. [2] da finden sich einige interessante Funktionen, an denen man sieht, dass awk doch gerne unterschaetzt wird. -- Wenn man nur einen Hammer als Werkzeug hat, sieht jedes Problem aus wie ein Nagel.