0

给定以下输入:

一个| 11 162 60 90 -- 141 184

乙| 231 322 -- 306 305 285 350

对于 A,我想检查 141 是否介于 (11,162) 或 (60,90) 之间。如果是,则打印“在 A 中,141 位于 (11,162) 之间”。

然后,我想检查 184 是否介于 (11,162) 或 (60,90) 之间。因为它没有,所以不需要打印任何内容。

同样,对于 B,我需要打印介于 (231, 322) 之间的数字。

我编写了以下 Perl 代码,但没有得到正确的输出。

#!/usr/bin/perl -w
open LIST, "input.txt";
while($line=<LIST>)
{
@elem=split (/\|/,$line);
@nextone=split("--",$elem[1]);
@nextoneone = split(" ",$nextone[0]);
@nexttwo=split(" ",$nextone[1]);

if ($nexttwo[0] > $nextoneone[0] && $nexttwo[0] < $nextoneone[1])
{
print"$elem[0]\t $nexttwo[0]\t $nextoneone[0]\t $nextoneone[1]\n";
}
elsif ($nexttwo[0] > $nextoneone[2] && $nexttwo[0] < $nextoneone[3])
{
print"$elem[0]\t $nexttwo[0]\t $nextoneone[2]\t $nextoneone[3]\n";
}
elsif ($nexttwo[1] > $nextoneone[0] && $nexttwo[1] < $nextoneone[1])
{
print"$elem[0]\t $nexttwo[1]\t $nextoneone[0] \t$nextoneone[1]\n";
}
elsif ($nexttwo[1] > $nextoneone[2] && $nexttwo[1] < $nextoneone[3])
{
print"$elem[0]\t $nexttwo[1]\t $nextoneone[2] \t$nextoneone[3]\n";
}
}
   close (LIST);
   exit;

我不知道每一行有多少个元素。因此,我不知道如何实现一个循环进行比较。任何有关如何改进代码的指导将不胜感激。

感谢您的帮助。

4

3 回答 3

1

首先,我会更改您的脚本的一些内容。1)使用严格 - 这意味着你会发现任何错别字

2)给变量更有意义的名字——我已经根据我所看到的改变了一些有意义的名字,但我不知道你的脚本做了什么,所以你可能有更好的名字

3) 在你开发的时候输出一些调试,这样你就可以看到它在做什么以及为什么它不工作

您将需要两个循环 - 一个循环遍历“--”左侧的字符串部分中的值,一个循环遍历右侧的条件。您想遍历外循环中的值,然后每次都应该遍历内循环中的所有条件。

    use strict;
    #!/usr/bin/perl -w
    open LIST, "input.txt";
    my $line;
    while($line=<LIST>) {
        my ($label, $content) =split (/\|/,$line);
        my ($conditionstring, $valuestring) =split("--",$content);
        my (@conditions) = split(" ",$conditionstring);
        my (@values) =split(" ",$valuestring);
        foreach my $this_val (@values) {
                my $matched_one_condition = 0;
                for (my  $f=0; $f< scalar(@conditions);$f+=2) {


                        print "Comparing $this_val to $conditions[$f] and to            $conditions[$f+1]\n";

                        if (($this_val > $conditions[$f]) && ($this_val < $conditions[$f+1])) {
                                $matched_one_condition= 1;

                        }
                }
                if ($matched_one_condition) {
                        print "$this_val\n";

                }
        }
}

注意 - 我把调试线留在了那里

于 2012-06-14T11:57:45.707 回答
0

如果您不知道它们的编号,请对这些值使用循环:

#!/usr/bin/perl
use warnings;
use strict;
use feature 'say';

while (<DATA>) {
    my ($header, $rangeS, $pointS) = /(.*)\|(.*) -- (.*)/;
    my @ranges = $rangeS =~ /([^ ]+ [^ ]+)/g;
    my @points = split / /, $pointS;

    for my $point (@points) {
        for my $range (@ranges) {
            my ($from, $to) = split / /, $range;
            if ($from <= $point and $point <= $to) {
                say "In $header, $point lies between ($from,$to)";
                last;   # Comment this line to get all the ranges for each point.
            }
        }
    }
}

__DATA__
A| 11 162 60 90 -- 141 184
B| 231 322 -- 306 305 285 350
C| 10 20 30 40 -- 1 2 3 4 5 6 7 8 9
D| 10 20 10 40 -- 1 10 20 40 10
于 2012-06-14T11:57:01.573 回答
0

我解决了你的问题。希望你能从中找到一些价值。我确实冒昧地对范围进行了排序,以处理 B 行的情况,例如 306、305。

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

while ( <DATA> ) {
    my @line = /\w+|\d+/g;
    my( $h, $ranges, $tests ) = (
        $line[0], [ [ sort @line[1,2] ], [ sort @line[3,4] ] ], [ @line[5,6] ]
    );
    map {
        my $test = $_;
        map {
            print "In $h, $test lies between (", join( ', ', @$_ ), ")\n"
                if grep { /^$test$/ } ( $_->[0] .. $_->[1] )
        } ( @$ranges )
    } @$tests
}

__DATA__
A| 11 162 60 90 -- 141 184
B| 231 322 -- 306 305 285 350
于 2012-06-14T14:06:39.553 回答