perl,在s上有奇怪的行为///

perl,在s上有奇怪的行为///,perl,Perl,我很不好意思问这个问题,因为它太简单了,但我看不出有什么不对。我有一个例行程序来清理ip范围的输入。这是一种蛮力,但我不知道还有更好的方法。我遇到的问题是,当我试图删除内部空间时,在条件块中只留下一个“-”或“,”作为分隔符,一个单独的前后空格将分隔符括起来。如果我清理了条件块外部的内部空间,这些空间将被正确删除。因此,在示例代码中,如果第1行上只有s/\s+//g,它会正确地清理,如果第2行和第3行上只有s/\s+//g,则空格左括号中的“-”和“,”。到底怎么了 use feature qw

我很不好意思问这个问题,因为它太简单了,但我看不出有什么不对。我有一个例行程序来清理ip范围的输入。这是一种蛮力,但我不知道还有更好的方法。我遇到的问题是,当我试图删除内部空间时,在条件块中只留下一个“-”或“,”作为分隔符,一个单独的前后空格将分隔符括起来。如果我清理了条件块外部的内部空间,这些空间将被正确删除。因此,在示例代码中,如果第1行上只有s/\s+//g,它会正确地清理,如果第2行和第3行上只有s/\s+//g,则空格左括号中的“-”和“,”。到底怎么了

use feature qw(say);
use Data::Dumper qw(Dumper);

$input = "   192.168.1.1       198.168.1.254     ";
buildIpRangeArray ($input);

$input = "   192.168.1.1  ,     198.168.1.254     ";
buildIpRangeArray ($input);

$input = "   192.168.1.1    -  198.168.1.254     ";
buildIpRangeArray ($input);

sub buildIpRangeArray {

    say "input: $input";

    $input = shift;
    $input =~ s/^\s+//;
    $input =~ s/\s+$//;
#    $input =~ s/\s+//g;                    # Line 1. 
                                            # Works if this is uncommented
                                            # and lines 2 and 3 are omitted

    if ( index($input,' ') >= 0) {
        $input =~ s/\s+/ /g;                # this works
        say "cleaned input 2: $input";
        @range = split(/ /,$input);
        say Dumper(@range);
    }
    elsif ( index($input,',') >= 0) {
        $input =~ s/\s+//g;                 # Line 2
        say "cleaned input 3: $input";
        @range = split(/,/, $input);
        say Dumper(@range);
    }
    elsif ( index($input,'-') >= 0) {
        $input =~ s/\s+//g;                 # Line 3
        say "cleaned input 4: $input";
        @range = split(/-/, $input);
        say Dumper(@range);
    }
}
The output:
input:    192.168.1.1       198.168.1.254     
cleaned input 2: 192.168.1.1 198.168.1.254
$VAR1 = '192.168.1.1';
$VAR2 = '198.168.1.254';

input:    192.168.1.1  ,     198.168.1.254     
cleaned input 2: 192.168.1.1 , 198.168.1.254
$VAR1 = '192.168.1.1';
$VAR2 = ',';
$VAR3 = '198.168.1.254';

input:    192.168.1.1    -  198.168.1.254     
cleaned input 2: 192.168.1.1 - 198.168.1.254
$VAR1 = '192.168.1.1';
$VAR2 = '-';
$VAR3 = '198.168.1.254';

第一个条件始终为true,因为字符串始终包含空格

因此,您必须以另一种方式编写if/elsif/elsif

if ( index($input,',') >= 0) {
    $input =~ s/\s+//g;                 # Line 2
    say "cleaned input 3: $input";
    @range = split(/,/, $input);
    say Dumper(@range);
}
elsif ( index($input,'-') >= 0) {
    $input =~ s/\s+//g;                 # Line 3
    say "cleaned input 4: $input";
    @range = split(/-/, $input);
    say Dumper(@range);
}
elsif ( index($input,' ') >= 0) {
    $input =~ s/\s+/ /g;                # this works
    say "cleaned input 2: $input";
    @range = split(/ /,$input);
    say Dumper(@range);
}

可能会产生您想要的结果。

您的第一个条件始终为true,因为字符串始终包含空格

因此,您必须以另一种方式编写if/elsif/elsif

if ( index($input,',') >= 0) {
    $input =~ s/\s+//g;                 # Line 2
    say "cleaned input 3: $input";
    @range = split(/,/, $input);
    say Dumper(@range);
}
elsif ( index($input,'-') >= 0) {
    $input =~ s/\s+//g;                 # Line 3
    say "cleaned input 4: $input";
    @range = split(/-/, $input);
    say Dumper(@range);
}
elsif ( index($input,' ') >= 0) {
    $input =~ s/\s+/ /g;                # this works
    say "cleaned input 2: $input";
    @range = split(/ /,$input);
    say Dumper(@range);
}

可能会产生您想要的结果。

如果您查看调试输出,很明显发生了什么。让我们以逗号作为第二个输出块

输入后,检查字符串中是否有空格“”。这里有:

           V
192.168.1.1 , 198.168.1.254
因此,对于逗号或破折号-,代码永远不会到达elsif。您可以验证这一点,因为您总是得到输入2,而不是输入3或输入4

下一步是清理空白,在这里你可以说它是有效的。您可以用一个空格替换大量空白。那就剩下了,在绳子上。现在你们在空格上分开,给你们

ip
,
ip
总的来说,您的代码相当幼稚。有很多重复,并且没有使用严格或使用警告,这使得调试更加困难。根据这段代码将如何使用,我建议进行一次巨大的简化

sub buildIpRangeArray {
    my $input = shift;

    say "input: $input";

    my @range = grep {$_} split /[^0-9.]+/, $input;
    say Dumper @range;
    return;
}

我们根据IP地址中不能包含的大量字符进行拆分。这也很幼稚,因为它不会验证您是否有实际的IP地址,但您的代码也不会。它适用于任意数量的空格或任何分隔符,即使它们是文本。我们需要删除前导或尾随空格中出现的空字符串。Perl中的空字符串计算结果为false,因此grep将过滤掉这些值。

如果查看调试输出,很明显发生了什么。让我们以逗号作为第二个输出块

输入后,检查字符串中是否有空格“”。这里有:

           V
192.168.1.1 , 198.168.1.254
因此,对于逗号或破折号-,代码永远不会到达elsif。您可以验证这一点,因为您总是得到输入2,而不是输入3或输入4

下一步是清理空白,在这里你可以说它是有效的。您可以用一个空格替换大量空白。那就剩下了,在绳子上。现在你们在空格上分开,给你们

ip
,
ip
总的来说,您的代码相当幼稚。有很多重复,并且没有使用严格或使用警告,这使得调试更加困难。根据这段代码将如何使用,我建议进行一次巨大的简化

sub buildIpRangeArray {
    my $input = shift;

    say "input: $input";

    my @range = grep {$_} split /[^0-9.]+/, $input;
    say Dumper @range;
    return;
}

我们根据IP地址中不能包含的大量字符进行拆分。这也很幼稚,因为它不会验证您是否有实际的IP地址,但您的代码也不会。它适用于任意数量的空格或任何分隔符,即使它们是文本。我们需要删除前导或尾随空格中出现的空字符串。Perl中的空字符串计算结果为false,因此grep将过滤掉这些值。

谢谢。我省略了我认为不相关的部分。我对Perl非常陌生,我知道我的大多数解决方案缺乏技巧。我正在努力。我要说的是,分手前的grep把我搞糊涂了。让我头晕hurt@Coltrane58别担心,我们都是从某个角度开始的。如果您向他人展示代码以帮助调试,请不要遗漏任何内容。这就像告诉一个机械师你的车没有启动,只是带着钥匙。你会及时了解哪些事情是相关的,哪些不是。只要问题仍然存在,您总是可以生成一个来显示问题。@Coltrane58对于grep,它使用一个块和一个列表,并丢弃块计算结果不为真的每个列表元素。这是一个过滤器。有点像map或reduce in,比如JavaScript,只是它过滤列表,而不是将内容应用到每个元素,或者将它们全部转换为单个值。主题$是当前值。我们所要做的就是检查它是否包含计算结果为true的内容。Perl中的False为0、空字符串、空列表和未定义。其他一切都是真的。那么grep括号中的$值是多少?我只熟悉戴牙套的格雷普。谢谢你的帮助和指点。Stackoverflow很棒,我一直在学习。我将接受您关于发布完整代码的建议。谢谢。我省略了我认为不相关的部分。我对Perl非常陌生,我知道的最多
我的许多解决方案缺乏技巧。我正在努力。我要说的是,分手前的grep把我搞糊涂了。让我头晕hurt@Coltrane58别担心,我们都是从某个角度开始的。如果您向他人展示代码以帮助调试,请不要遗漏任何内容。这就像告诉一个机械师你的车没有启动,只是带着钥匙。你会及时了解哪些事情是相关的,哪些不是。只要问题仍然存在,您总是可以生成一个来显示问题。@Coltrane58对于grep,它使用一个块和一个列表,并丢弃块计算结果不为真的每个列表元素。这是一个过滤器。有点像map或reduce in,比如JavaScript,只是它过滤列表,而不是将内容应用到每个元素,或者将它们全部转换为单个值。主题$是当前值。我们所要做的就是检查它是否包含计算结果为true的内容。Perl中的False为0、空字符串、空列表和未定义。其他一切都是真的。那么grep括号中的$值是多少?我只熟悉戴牙套的格雷普。谢谢你的帮助和指点。Stackoverflow很棒,我一直在学习。我们将接受您关于发布完整代码的建议。