Shell 基于分钟的列总和
下面是我的输入文件:Shell 基于分钟的列总和,shell,unix,awk,Shell,Unix,Awk,下面是我的输入文件: 第一列是一天中的小时和分钟的组合 第二列是计数 数据是按分钟计算的 我需要通过对每一个分块进行求和,将数据转换为分块,即[1-5、6-10等等]。我需要这些数据在jfree图表中绘图。请建议如何获得输出 输入: 11.01:5 11.02:4 11.03:3 11.04:8 11.05:2 12.11:3 12.12:4 12.13:1 12.15:0 13.03:04 22.56:01 22.57:03 22.58:2 23.00:0 输出: 11.05:22 12
- 第一列是一天中的小时和分钟的组合
- 第二列是计数
11.01:5
11.02:4
11.03:3
11.04:8
11.05:2
12.11:3
12.12:4
12.13:1
12.15:0
13.03:04
22.56:01
22.57:03
22.58:2
23.00:0
输出:
11.05:22
12.15:8
13.05:4
23.00:6
这个问题可以用一百万种不同的方法来解决:sed、awk、python等等 下面是使用常用bash命令的方法
#!/bin/bash
# extract the unique set of hours from the input (i.e. 11, 12, 13, 22, 23)
#
hours=$(cut -f 1 -d . test.txt | sort -u)
for hour in $hours; do
# initialize sum for this hour
#
count=0
# extract the number following the ':'
#
for x in $(grep "^$hour" test.txt | cut -f 2 -d :); do
# sum up the numbers following the ':'
#
count=$(($count + $x))
done
# Extract the last timestamp for the given hour
#
t=$(grep "^$hour" test.txt | tail -1 | cut -f 1 -d :)
# Print the desired output of timestamp:sum
#
echo $t:$count
done
以下是输出:
11.05:22
12.15:8
13.03:4
22.58:6
23.00:0
您的输入存储在文件test.txt中:
11.01:5
11.02:4
11.03:3
11.04:8
11.05:2
12.11:3
12.12:4
12.13:1
12.15:0
13.03:04
22.56:01
22.57:03
22.58:2
23.00:0
让我指出您在脚本中看到的一些命令
cut
用于从输入中提取列cut-f1-d。
将从您的输入中提取小时数<代码>-f 1表示打印列1,而-d.
表示使用“.”作为去污剂tail-f1
打印tail输入的最后一行sort-u
从输入中删除重复的行awk -F '[.:,]' -v OFS=: '{
p=5*int(($2+4)/5);
$1=1*$1;
if(p==60){
p="0";
$1++
}
k=sprintf("%02d.%02d", $1, p)
}
!s[k]{
b[++n]=k
}
{
s[k]+=$3
}
END{
for (i=1; i<=n; i++)
print b[i],s[b[i]]
}' file
11.05:22
12.15:8
13.05:4
23.00:6
awk-F'[.:,]'-vofs=:'{
p=5*int($2+4)/5);
$1=1*$1;
如果(p==60){
p=“0”;
$1++
}
k=sprintf(“%02d.%02d”,$1,p)
}
!s[k]{
b[++n]=k
}
{
s[k]+=$3
}
结束{
对于(i=1;i这是一份草案。一旦您展示了一些尝试,我将提供一种更通用的方法:
awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; a[$1"."r]+=$3} END {for (i in a) print i, a[i]}' file
对于给定的输入,它将返回:
22.60:6
13.5:4
12.15:8
23.5:0
11.5:22
关键是把每一个1,2,3,4和5映射到5。我这样说:
d -> d-1 -> (d-1)/5 (int division) -> (d-1)/5 * 5
要确保没有出现分钟数60
,可以添加一些条件:如果(r==60){r=0;$1++}
:
$ awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; if (r==60) {r=0; $1++}; a[$1"."r]+=$3} END {for (i in a) print i, a[i]}' file
23.0:6
13.5:4
12.15:8
23.5:0
11.5:22
您还可以做一些奇特的事情,例如打印一个前导0
0分钟:
再来一杯
如果你想四舍五入到最接近的5
awk -F"[.:]" '{$2=(t=($2%5))>2?$2-t+5:$2-t;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
END{for(i in b)print i"."b[i]":"a[i]}' file
如果你想把所有不是5的倍数的东西都四舍五入
awk -F"[.:]" '{$2=$2%5!=0?$2-($2%5)+5:$2;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
END{for(i in b)print i"."b[i]":"a[i]}' file
四舍五入至5的最接近倍数的输出
四舍五入到下一个5的倍数
正如您在输出中看到的,这将四舍五入到最接近的5,这就是22.55存在的原因
四舍五入的工作原理
当一个数除以另一个数时,模数给出余数
24/5=4剩余4
所以
24%5=4
所以要把数字四舍五入到X的下一个倍数,我们只需减去余数
N-(N%X)
24-(24%5)
将始终是X的倍数(向下舍入)
为了进行四舍五入,我们简单地说,如果模的结果大于X的一半(在本例中为5),则将X与结果相加,以四舍五入到X的下一个倍数
(N-(N%X))+X
(24-(24%5))+5
不确定这是否是进行循环的最佳方式,但它确实有效:)是的。因为没有13.01,13.02的数据。我只想在第5分钟内得到输出。您可以详细说明一下,它不是很清楚。@user1580770您不想四舍五入到最接近的5吗?因为22.56
和22.57
都会四舍五入到22.55
@Jidder显然都会四舍五入到上面的5.1,2,3,4和5-->5,而6,7,8,9,0->0。我在回答中做了一个小图表:D@fedorqui我知道,我只是想知道OP是否意识到这就是他们所做的,我在我的答案中添加了这两个,以防万一:)我使用了模数,虽然:D(你的整数除法几乎是mod)04:15,39 04:20,225 04:25,208 04:30,263 04:35,311 04:40,270 04:45,287 04:50,264 04:55,261 5:00,191 05:00,42 05:05,221 05:10,227 05:15,225 05:20,219 05:25,208 05:30,207 05:35,214 05:40,207 05:45,250 05:50,241 05:55,243 6:00,207 06:00,46 06:05,233 06:10,243 06:15,260 06:20,241 06:25,244 06:30,242 06:35,222 06:40,241 06:45,287 06:50,226 06:55,222 7:00,168 07:00,47 07:05438 07:10260 07:15256 07:20290 07:25256 07:30249 07:35249 07:40256 07:45299 07:50244 07:55284 8:00229 08:00,56 08:05283 08:10263 08:15302 08:20154难以从评论中阅读,你能用这个编辑你的问题吗data@user1580770:您的原始输入是hh.mm:count
格式,但您拥有的是re是hh:mm,count
格式,它们都是不同的。我正在进行更改以处理这两种格式,但您应该在问题中澄清这一点。
awk -F"[.:]" '{$2=$2%5!=0?$2-($2%5)+5:$2;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
END{for(i in b)print i"."b[i]":"a[i]}' file
11.5:22
12.15:8
22.55:4
13.5:4
23.0:2
11.05:22
12.15:8
13.5:4
23.00:6