将每个范围(行)分成两个子范围

时间:2013-08-07 15:07:22

标签: r perl awk

我有这样的输入:

120-160

200-220

400-500
.
.
.

我会链接将每个范围(行)分成两个子范围:

120-140 141-160

200-210 211-220

400-450 451-500
.
.
.

然后将每列(范围)打印到不同的文件中。

文件1:

120-140 

200-210 

400-450
.
.
.

文件2:

141-160

211-220

451-500
.
.
.

我什么也做不了,也不知道怎么做。

非常感谢

3 个答案:

答案 0 :(得分:4)

你可以使用bash:

while IFS=- read min max; do
    mid=$(( (min+max)/2 ))
    printf "%d-%d\n" $min $mid >> file.1
    printf "%d-%d\n" $((mid+1)) $max >> file.2
done < input.file

awk将是

awk -F- -v OFS=- '{
    mid = int(($1+$2)/2)
    print $1, mid   > "file.1"
    print mid+1, $2 > "file.2"
}' input.file

答案 1 :(得分:2)

Perl解决方案。保存为break-range.pl,以perl break-range.pl input运行。

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

open my $F1, '>', 'file1' or die $!;
open my $F2, '>', 'file2' or die $!;

while (<>) {
    chomp;
    if (my ($low, $high) = /([0-9]+)-([0-9]+)/) {
        my $middle = int(($low + $high) / 2);
        print $F1 "$low-$middle\n";
        print $F2 $middle + 1, "-$high\n";
    }
}
close $F1;
close $F2;

对于非固定数量的输出文件,您可以使用以下内容,将其作为break-rangle.pl number-of-files input运行。请注意,如果文件数大于间隔大小,它可能不起作用。

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

my $number = shift;

my @FH;
for my $i (0 .. $number - 1) {
    open $FH[$i], '>', "file$i" or die $!;
}

while (<>) {
    chomp;
    if (my ($low, $high) = /([0-9]+)-([0-9]+)/) {
        my $step = ($high - $low) / $number;
        for my $i (0 .. $number - 1) {
            print {$FH[$i]} int($low + $i * $step) + ($i > 0), '-',
                            int($low + ($i + 1) * $step), "\n";
        }
    }
}
close $_ for @FH;

答案 2 :(得分:1)

这是一个R解决方案:假设您已将数据导入向量input

input <- c("120-160", "200-220", "400-500")
ranges <- strsplit(input, "-")
ranges <- lapply(ranges, as.numeric)
ranges <- lapply(ranges, function(x) c(x[1], mean(x), x[2]))

output1 <- sapply(ranges, function(x) sprintf("%d-%d", x[1], x[2]))
output2 <- sapply(ranges, function(x) sprintf("%d-%d", x[2]+1, x[3]))

然后,您可以使用writeLines来编写这两个文件。