区分一行中的多个正则表达式命中?

时间:2013-12-13 09:30:50

标签: regex perl

我正在尝试用Perl中的随机数替换IP地址:

while (my $line = <file>){
    $line =~ $regex{'ipadress'};

    my $rand0 = int(rand(256));
    my $rand1 = int(rand(256));
    my $rand2 = int(rand(256));
    my $rand3 = int(rand(256));

    $& = "$rand0.$rand1.$rand2.$rand3\n";`
}

问题在于,在某些情况下,一行中有多个IP地址 如何避免它们都得到相同的随机数?

3 个答案:

答案 0 :(得分:4)

这可能会有所帮助:

sub rip { return join(".", map { int(rand(256)) } (1..4) ) } 

open my $f, '<', 'input' or die($!);
while (my $line = <$f>){
    $line =~ s/$regex{'ipadress'}/rip()/eg;
}
close($f);

答案 1 :(得分:4)

一开始$&是只读的,你无法像这样修改目标字符串。

我也不确定你的哈希的密钥是否真的是ipadress(只有一个d),但我确信你可以修复它。

我会写这样的东西。替换运算符上的/e修饰符会导致替换字符串执行以确定要替换匹配项的内容。 join语句生成从0到255的四个字节值,并用点连接它们以形成随机地址。

while (my $line = <$fh>) {
  $line =~ s{$regex{ipadress}}{
    join '.', map int(rand(256)), 0..3
  }eg;
  print $line;
}

答案 2 :(得分:1)

这些答案是确保为每个IP地址挑选新随机数的好方法。但海报的主要问题是,“如何避免它们都获得相同的随机数?”并且我不清楚它们是否意味着“为行中的每个IP地址获取四个随机数”或“保证没有两个随机选择的IP地址相同。”

如果是后者:连续两次调用rand(256)四次得到相同结果的概率是2 32 中的一个,这似乎不值得担心,但是如果您需要保证它们不同,您可以保留已经选择的地址哈希值,并在每次生成新地址时更新它。窃取@ perreal的解决方案:

sub rip {
    my $picked_addrs = shift;
    my $new_addr;
    do {
        $new_addr = join(".", map { int(rand(256)) } (1..4) );
    } while defined($picked_addrs->{$new_addr});
    $picked_addrs->{$new_addr} = 1;
    return $new_addr;
} 

open my $f, '<', 'input' or die($!);
while (my $line = <$f>){
    my %picked_addrs;
    $line =~ s/$regex{'ipadress'}/rip(\%picked_addrs)/eg;
}
close($f);

如果你想确保你永远不会在文件的任何地方选择两次相同的地址,只需在%picked_addrs循环之外声明while,这样就不会为每一行重置:< / p>

open my $f, '<', 'input' or die($!);
my %picked_addrs;
while (my $line = <$f>){
    $line =~ s/$regex{'ipadress'}/rip(\%picked_addrs)/eg;
}
close($f);