0

I have two input files. One has namelist, mm:dd form, duration of usage and other host name stuff in each line. The other one is the one that I generated that has a set of namelist in each line that does not repeat. I am trying to write a shell command to iterate through the file with the namelist, store them as a variable and check with the other file to match the name and then output the total duration of usage for each person and then output a file containing and information. Is there anyway I can use awk or anything to do the work?

I figured the command: for word in $(cat namelist); do echo $word; done but this is only for iterating through one file. What I wanna do is something like this:

for word in namelist.txt:
 for words in info_file.txt (field $1):
   if word == words:
     (calculating usage of time) 
     print(word, ':', usage of time)

I have already figured out the codes to calculate the usage of time. It's just how to do this operation that is my problem right now. Could anybody please help?

-----------------further explanation So I have one file containing information of the time that the user consumed to login into the host that each row has the information of name, date(mm:dd:hh:mm), initial time, end time, time duration and host name. What I want to achieve is to output a file with each Month as a title(for example: [April]) and then calculate the time duration of each user who login into the host. They might have multi logins so their names appear multiple times with the other informations in each rows. I have generated this file that has all the user names that has been login during past half a year. I am trying to generate output file with each Month Name as a title, and group by month and then match the names in the file with the namelist that I generated to get their time duration calculated and printed into the output file on the same row with their name printed. I have already figured out how to do the calculations. So right now it's just how do I do the steps of matching names that confuses me

input file:

sdou     pts/11       Thu Dec 10 05:24 - 12:11 (2+06:46)    131.243.186.99
sdou     pts/10       Thu Dec 10 05:04 - 12:11 (2+07:06)    131.243.186.99
sdou     pts/9        Thu Dec 10 03:26 - 12:11 (2+08:45)    131.243.186.99
ermartin pts/0        Sat Dec 12 12:37 - 13:44  (01:06)     c-24-130-14-154.hsd1.ca.comcast.net
ermartin pts/0        Sat Dec 12 12:18 - 12:31  (00:13)     c-24-130-14-154.hsd1.ca.comcast.net

sample output:

[Dec]
sdou 94.xxxhours
ermartin 1.19hours
Edccccch
  • 19
  • 1
  • 3
  • 8
  • I'm not sure I understand the question, but you _may_ be looking for the [join](http://linux.die.net/man/1/join) utility. – zwol Jul 22 '16 at 20:44
  • I am looking into this utility right now. Thanks! And also I just added a further explanation – Edccccch Jul 22 '16 at 20:51
  • will be much easier to help you if you include **small** sample data (3 columns worth sounds like it should be enough), and required output from that data. use the `{}` format tool at the top left of the edit box on highlighted text to format as code/data/output/ErrMsgs. Good luck. – shellter Jul 22 '16 at 20:54
  • 1
    Also, your project sounds like something databases are designed for. If you're doing this for a business, that is certainly the long-term solution. Good luck. – shellter Jul 22 '16 at 20:54
  • Just added. Please let me know if there's more I can show to make it more clear! And yes this is a business-like database thing so I have to make sure the solution would be long term – Edccccch Jul 22 '16 at 20:59
  • The field in (2+06:46) is the duration. 2 is days and 06:46 is 6hours46minutes – Edccccch Jul 22 '16 at 20:59
  • Now that I see the data and the required output, I can say definitely that `awk` would be a suitable language for this problem. Work thru the `awk` tutorial at http://grymoire.com/Unix/Awk.html, and add your best attempt to solve your problem to your Q. a hint : `awk '{names[$1]=$1; days=$9; print "days="days ; sub(/\+.*$/,"",days); sub(/\(/,"",days); print "days="days; totHrs[$1]+=days*24}END{for (n in names) {print names[n] "\t" totHrs[n]}}'' inputFile`. Debug this to work and you'll be well on your way. (you'll need a few more variables, but get this to work first. Good luck. – shellter Jul 23 '16 at 01:46
  • Thanks so much! I'll definitely look into this! – Edccccch Jul 23 '16 at 01:53
  • Are you sure that's the expected output given that input? I've spent a lot of time debugging [my script](http://stackoverflow.com/a/38543563/1745001) trying to figure out why it's producing different output from the output you say it should produce so I'm really hoping those aren't just random, disconnected numbers you pulled out of the air and really ARE the expected output given that input and can explain why they are. – Ed Morton Jul 23 '16 at 15:49
  • Possible duplicate of [inner join on two text files](http://stackoverflow.com/questions/13272717/inner-join-on-two-text-files) – tripleee Jul 23 '16 at 16:35

2 Answers2

2

I thought this was what you wanted (uses GNU awk 4.* for true multi-dimensional arrays):

$ cat tst.awk
{
    n = split($9,t,/[()+:]/)
    hours = t[n-3]*24 + t[n-2] + t[n-1]/60
    tot[$4][$1] += hours
}
END {
    for (month in tot) {
        print "["month"]"
        for (user in tot[month]) {
            print user, tot[month][user] "hours"
        }
    }
}

$ awk -f tst.awk file
[Dec]
sdou 166.617hours
ermartin 1.31667hours

but the output numbers don't match your expected values:

[Dec]
sdou 94.xxxhours
ermartin 1.19hours

I've spent a lot of time trying to figure out why they're different but I can't. Sorry, hope this helps anyway.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
-1

I solved this using perl through this code from what I understood from you question.

#!/usr/bin/perl -w
use strict;
use warnings;

use Data::Dumper;   # $fields[3] => Month $fields[0] => user $fields[8] => Time

my $user_time = {};
my $time = {};
open my $READ , '<', 'test' or die;

while(my $line = <$READ>){
    my @fields = split(' ', $line);

    my $user = $fields[0];
    my $month = $fields[3];

    $fields[8] =~ m/([\d]*)\+?([\d]{2}):([\d]{2})/; #time format
    my $min = $3;
    my $hr = $2;
    my $day = $1;
    $day = 0 if (!$day);
    if (!exists $user_time->{$month}->{$user}){
        $time = {};
    }
    $time->{'day'} += $day*24;
    $time->{'hr'} += $hr;
    $time->{'min'} += $min;

    $user_time->{$month}->{$user} = $time;
}
close $READ;
foreach my $month (keys %$user_time){
    print "[$month]\n";
    my $user_hash = $user_time->{$month};
    foreach my $user (keys %$user_hash){
        my $time = $user_hash->{$user};
        print "$user\t". $time->{'day'}.'.'.$time->{'hr'}.'.'.$time->{'min'}."hours\n";
    }
}

INPUT FILE:

sdou     pts/11       Thu Dec 10 05:24 - 12:11 (2+06:46)    131.243.186.99
sdou     pts/10       Thu Dec 10 05:04 - 12:11 (2+07:06)    131.243.186.99
sdou     pts/9        Thu Dec 10 03:26 - 12:11 (2+08:45)    131.243.186.99
ermartin pts/0        Sat Dec 12 12:37 - 13:44  (01:06)     c-24-130-14-154.hsd1.ca.comcast.net
ermartin pts/0        Sat Dec 12 12:18 - 12:31  (00:13)     c-24-130-14-154.hsd1.ca.comcast.net

OUTPUT:

[Dec]
ermartin 0.1.19hours
sdou     144.21.97hours

Hope this helps.

AbhiNickz
  • 1,035
  • 2
  • 14
  • 32