[H-GEN] Shell script problem.

Anthony Towns aj at azure.humbug.org.au
Sat Jun 6 03:22:19 EDT 1998


On Fri, Jun 05, 1998 at 10:02:22AM +0800, Tom Atkinson wrote:
> > is return the line number of the smallest error.  The problem is that the
> > number is a float.  ie.
> For simplicity, how about the following awk script?
> BEGIN { flag=0 }
> {
>  if (flag == 0 || $2 < smallest)
>     {
>      flag = 1;
>      smallest = $2;
>      lineno = $1;
>     }
> }           
> END { print lineno, smallest }

Personally, I *never* write Awk /scripts/. [0]

Awk one liners, on the other hand, are fun.

awk 'BEGIN { f=1;s=0 } { if($2<s || f) {f=0;s=$2;l=$0} } END { print l }'

(0 is false, and non-zero is true, so you can just say "if(f)" to see if
f is non-zero; you can use $0 to refer to the whole line at once; and
you don't have to stick to good coding style when writing pointless
little scripts that took five minutes to invent -- you don't maintain
such things, you rewrite them).

You can go a little further and rely on f and s being initialized to 0,
but I personally can't cope with that. If you know a value that you're
always going to have at least some (or, better, all) your errors less
than, you can use that as your initial value for "s", and get rid of
"f" entirely, too. But you need to know something about the problem
domain dor that.

If you're using awk, you can get rid of the "grep" and "sed" parts to
isolate the original file to just the error value, too. So

	Data item: 1
	blah de blah blah blah
	Error: approx 3.44332e10 +/- 0.3 (scaled)

	Data item: 2
	tra lalalalalal
	Error: approx 9.44503e04 +/- 0.3 (scaled)

Gets parsed by using:

	/^Data item:/ { DATA=$3 }
	/^Error:/ { if ( ... ) { ...; min_data=DATA } }
	END { print "Data with least error: " DATA " (error " least ")" }

Using awk for things like this works especially well, because you can
cope comfortable even if it didn't understand "e+07" itself, by saying
something like:

	/* $2 = n.nnnnnE+mm */
	split( $2, X, "[eE]" );  /* X[1] = n.nnnnn, X[2] = +mm */
	if ( f || X[2] < oldexp || (X[2] == oldexp && X[1] < oldval) ) {
		f = 0;
		oldexp = X[2];
		oldval = X[1];
	}

If you wanted, you could split it up further, with a regexp "[eE.]"
instead of just "[eE]".

Cheers,
aj

[0] Some would claim that's a learned habit, and is solely due to 
    Emacs' startup time. 

    Such people are probably too busy working out whether they have to
    hit "escape" or "i" next to make such claims coherently, however.

    Separate movement and typing modes, my foot.

-- 
Anthony Towns <aj at humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. PGP encrypted mail preferred.

          ``It's not emacs, or vi. It's just an editor.''
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 434 bytes
Desc: not available
URL: <http://lists.humbug.org.au/pipermail/general/attachments/19980606/af4b603e/attachment.sig>


More information about the General mailing list