使用 bash 或 awk 或 perl 创建 CDF 数据

使用 bash 或 awk 或 perl 创建 CDF 数据

我们有一些数据,例如:

12 0
13 0 
20 0
25 1
64 4
77 1
89 100
1201 204

我想获得这个输出:

3 0
5 1
6 4
7 100
8 204

解释:我们有 3 个度为 0 的 AS(自治系统),然后有 5 个度为 1 或小于 1 的 AS,还有 6 个度为 4 或小于 4 的 AS,并且...

有很多行(100,000)我猜这是分布的 CDF,这是解析 bgpdump 数据的一部分,我想计算这些数字。再次感谢您的帮助

答案1

这是一个简单的 Perl 脚本,可以为您完成这项工作:

#!/usr/bin/perl
use strict;
my %result;
my @data;
my %data;
my @degrees;
my $infile = shift() || die "Usage: $0 <file>\n";

# Read source data from input file
open IN, '<', $infile
    or die "Couldn't open data file: $!\n";
while (my $line = <IN>) { chomp $line; push @data, $line; };
close IN;

# Convert data lines to hash
foreach my $line (@data) {
    my ($count, $degree) = split(/\s+/, $line);
    $data{$degree}++;
};

# Get sorted degrees for count-up iteration
@degrees = sort { $a <=> $b } keys %data;

# Iterate degrees, adding each one's system count to result for this degree
# and all higher degrees
for (my $i = 0; $i < scalar(@degrees); $i++) {
    my $degree = $degrees[$i];
    my $count = $data{$degree};
    for (my $j = $i; $j < scalar(@degrees); $j++) {
        $result{$degrees[$j]} += $count;
    };
};

# Output result counts
foreach my $degree (sort { $a <=> $b } keys %result) {
    print "$result{$degree} $degree\n";
};

对于大型输入数据集,此脚本将需要大量内存;它会在操作之前读取整个输入文件,因为输入文件看起来似乎没有排序,而操作之前需要按度对数据进行排序。也就是说,它应该能很好地完成您的工作 - 如果不行,请告诉我!

答案2

这是一个可以完成这个工作的快速 100% bash 脚本:

a=()
while read _ n; do
    [[ -n $n ]] && ((++a[n]))
done < datafile.txt
c=0
for i in ${!a[@]}; do
    echo "$((c+=a[i])) $i"
done

如果您想要一个可以从命令行调用的脚本:

#!/bin/bash

a=()
while read _ n; do
    [[ -n $n ]] && ((++a[n]))
done < "$1"
c=0
for i in ${!a[@]}; do
    echo "$((c+=a[i])) $i"
done

或者如果你想用一句话来打动你的祖母:

a=(); while read _ n; do [[ -n $n ]] && ((++a[n])); done < datafile.txt; c=0; for i in ${!a[@]}; do echo "$((c+=a[i])) $i"; done

它在 2.6GHz 奔腾双核处理器上运行 100000 行文件大约需要 2-3 秒。

编辑

解释:

第一个循环:

  • 我们初始化a为一个空数组:a=()
  • 我们datafile.txt逐行读取文件。每行有两个字段,只有第二个字段放在变量名称中n
  • 如果n非空(这是测试,我们增加数组第个键[[ -n $n ]]的值;这就是该行的作用。是 bash 的算术上下文。na((++a[n]))((...))
  • 读取完所有文件后,我们得到一个数组ak第个字段正好是度等于的自治系统的数量k

然后是第二个循环:

  • 循环之前,变量c设置为0。
  • for i in ${!a[@]}; do将循环遍历数组的所有键a
  • $((c+=a[i]))将的值添加a[i]c并扩展到该值。该值将与附加到其上的echo键的值一起进行处理。i

希望这可以帮助!

相关内容