Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell-用户上列的和_Shell - Fatal编程技术网

Shell-用户上列的和

Shell-用户上列的和,shell,Shell,基本上,我有两个专栏。第一个代表用户,第二个代表用户在服务器上花费的时间。所以我想计算每个客户机在服务器上花费的时间 user1 21:03 user2 19:55 user3 20:09 user1 18:57 user1 19:09 user3 21:05 user4 19:57 假设我有这个。我知道如何分割,但有一个问题。每当我执行awk-F:'{print$1}时,它都会打印用户和时间的第一个参数(:之前的数字),当我执行awk-F:'{print$2}时,它只打印:之后的数字。在所有

基本上,我有两个专栏。第一个代表用户,第二个代表用户在服务器上花费的时间。所以我想计算每个客户机在服务器上花费的时间

user1 21:03
user2 19:55
user3 20:09
user1 18:57
user1 19:09
user3 21:05
user4 19:57
假设我有这个。我知道如何分割,但有一个问题。每当我执行
awk-F:'{print$1}
时,它都会打印用户和时间的第一个参数(
之前的数字),当我执行
awk-F:'{print$2}
时,它只打印
之后的数字。在所有的总数之后,我想得到

user1 59:09
user2 19:55
user3 41:14
user4 19:57

下面是一个可能的解决方案:

perl -ne '/^(\S+) (\d\d):(\d\d)$/ or next; $t{$1} += $2 * 60 + $3; END { printf "%s %02d:%02d\n", $_, $t{$_} / 60, $t{$_} % 60 for sort keys %t }'
或者使用更好的格式:

perl -ne '
    /^(\S+) (\d\d):(\d\d)$/ or next;
    $t{$1} += $2 * 60 + $3;
    END {
        printf "%s %02d:%02d\n", $_, $t{$_} / 60, $t{$_} % 60
            for sort keys %t;
    }
'
我们在所有输入行上循环(
-n
)。我们确保每一行都匹配模式
\S+\d\d:\d\d
(即一个或多个非空格字符、一个空格、两个数字、一个冒号、两个数字的序列),否则我们将跳过它

我们在哈希
%t
中累积每个用户的秒数。键是用户名,值是数字


最后,我们以格式良好的方式打印
%t
的内容。

这是一个awk解决方案

cat 1.txt | awk '{a[$1]+=substr($2,0,2)*60+substr($2,4)} END {for(i in a) printf("%s %02d:%02d\n", i,a[i]/60,a[i]%60)}'
user1 59:09
user2 19:55
user3 41:14
user4 19:57
首先构造一个索引为$1的数组,其值=将时间转换为整数乘以分钟*60+秒

{a[$1]+=substr($2,0,2)*60+substr($2,4)}
然后以所需格式打印数组,该格式将整数转换为mi:ss格式

printf("%s %02d:%02d\n", i,a[i]/60,a[i]%60)

如果要使用
awk
(并且假设持续时间始终为
hh:mm
,尽管它们的大小可以是任意的),下面将实现此技巧:

{
    split($2, flds, ":")               # Get hours and minutes.
    mins[$1] += flds[1] * 60 + flds[2] # Add to initially zero array item.
}
END {
    for (key in mins) {                # For each key in array.
        printf "%s %d:%02d\n",         # Output specific format.
            key,                       # Key, hours, and minutes.
            mins[key] / 60,
            mins[key] % 60
    }
}
这是扩展的、可读的变体,压缩的变体显示在以下转录本中,以及预期的输出:

pax> awk '{split($2,flds,":");mins[$1] += flds[1] * 60 + flds[2]}END{for(key in mins){printf "%s %d:%02d\n",key,mins[key]/60,mins[key]%60}}' testprog.in

user1 59:09
user2 19:55
user3 41:14
user4 19:57

请记住,当用户输入超过24小时时,您没有指定输入格式。如果出现类似
25:42
,脚本将按原样工作

相反,如果它决定将几天划分为
1:01:42
而不是
25:42
),则需要调整分钟的计算方式。通过检查
fld
数组大小(在脚本主体中,非
END
位),可以相对轻松地完成此操作(包括仅分钟输入的可能性):

num = split($2, flds, ":")
if (num == 1)      { add = flds[1] }
else if (num == 2) { add = flds[1] * 60 + flds[2] }
else               { add = flds[1] * 1440 + flds[2] * 60 + flds[3] }
mins[$1] += add