[comp.unix.shell] Mixing awk with C and sh.

sdougiama@cc.curtin.edu.au (05/31/91)

New Bruce - Another tube... and a question.
 
I have a file of lines, each line has the same number of fields, separated
by tabs.  The second field in each line is a date in the form: 'dd-mmm-yy'

eg.  31-May-91
 
What I want to do is print all the lines with a date that is some x days
before the current date.  I have already written a C program that takes
two dates in a variety of formats and returns the number of days between them.

eg.
# compare_date  21-Apr-91 31/5/91
40
#
 
So what I'd like to do is write some awk program that does:
 
for each line in the file
  extract date
  difference <= compare_date  extractdate  currdate
  if difference < x then
     output the current line
endfor
 
However I can't think of a way to do this, not being very experienced with awk.
Is there someone there who could help me out?
Is there a simpler way?  Is there *any* way?
I'd like a simple awk or sh solution if possible, but any help is appreciated.

[ This will be part of a portable shell-based BBS I'm writing.
  The file in question is a catalog of uploaded files, and I want to list
  all the recent uploads within certain time frames. ]
 
Martin
,-------------------------+---------------------------------------n------.
| "There's nothing quite  | Martin Dougiamas.                ,-\_/ \     |
|  so fun as a good,      | SDOUGIAMA@cc.curtin.edu.au      /  |    \    |
|  solid poke in the eye  | Curtin University               \  |_   /    |
|  with a pencil."  o.x   | Perth, Western Australia. ---->  x-' `_'     |
`===================\_/===+=======================================V======'

tchrist@convex.COM (Tom Christiansen) (06/01/91)

From the keyboard of sdougiama@cc.curtin.edu.au:
:New Bruce - Another tube... and a question.
: 
:I have a file of lines, each line has the same number of fields, separated
:by tabs.  The second field in each line is a date in the form: 'dd-mmm-yy'
:
:eg.  31-May-91
: 
:What I want to do is print all the lines with a date that is some x days
:before the current date.  I have already written a C program that takes
:two dates in a variety of formats and returns the number of days between them.
:
:# compare_date  21-Apr-91 31/5/91
:40


You might as well just use getdate from the the C news distribution
instead of recreating the wheel. (Although I'd fix getdate to read from
stdin and write to stdout, and flush each print.)  

Hmm... if you accept both dd-mm-yy and mm-dd-yy, then could you please
tell me what 3/4/90 means?  Is that 3-Apr-90 or 4-Mar-90?  You can't
disambiguate that.

:So what I'd like to do is write some awk program that does:
: 
:for each line in the file
:  extract date
:  difference <= compare_date  extractdate  currdate
:  if difference < x then
:     output the current line
:endfor
: 
:However I can't think of a way to do this, not being very experienced with awk.
:Is there someone there who could help me out?
:Is there a simpler way?  Is there *any* way?
:I'd like a simple awk or sh solution if possible, but any help is appreciated.

You would have to use new awk and use getlines to read from your C
program, which you would open pipes to.  If you have old awk on even some
of your systems, you're out of luck.  Since you'd have to make sure of
this anyway, you could just make sure perl is installed instead, which
would give you a lot more programming power.

Basically in [gn]awk you should do something like this:

    "/usr/local/lib/news/newsbin/getdate" " "  $2 | getline then;

you should cache the current date for compares.

    #!/usr/local/bin/gawk
    BEGIN { "date" | getline now; }
    {
	"yourprogram" " " now " " $2 | getline delta;
	if (delta > 40) next;
	print;
    }

or somesuch.
    

Here's a working perl version that should give you the idea.

    #!/usr/bin/perl

    $GETDATE = '/usr/local/lib/news/newsbin/getdate';
    $SECS_PER_DAY = 24 * 60 * 60;
    $NOW = time;
    $DELTA = 40;

    while (<>) {
	next unless /^\s*\S+\s+(\S+)/;
	$then = `$GETDATE $1`;
	next if ($NOW - $then) / $SECS_PER_DAY > $DELTA;
	print;
    } 

To me, this is pretty easy.  I think I could probably work up a
shell solution if I were forced to, but I hate reading files with 
the shell.


--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
		"So much mail, so little time."