use shell to iterate through a file

2019-03-06 07:09发布

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

2条回答
不美不萌又怎样
2楼-- · 2019-03-06 07:25

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.

查看更多
做自己的国王
3楼-- · 2019-03-06 07:41

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.

查看更多
登录 后发表回答