perl - 如何从 Perl 中的 2 个文件之一删除公共(public)行?

标签 perl

我有 2 个文件,一个小的和一个大的。小文件是大文件的子集。

例如:

小文件:

solar:1000
alexey:2000

大文件:

andrey:1001
solar:1000
alexander:1003
alexey:2000

我想删除 Big.txt 中也存在于 Small.txt 中的所有行。换句话说,我想删除大文件中与小文件共有的行。

所以,我写了一个 Perl 脚本,如下所示:

#! /usr/bin/perl

use strict;
use warnings;

my ($small, $big, $output) = @ARGV;

open(BIG, "<$big") || die("Couldn't read from the file: $big\n");
my @contents = <BIG>;
close (BIG);

open(SMALL, "<$small") || die ("Couldn't read from the file: $small\n");

while(<SMALL>)
{
    chomp $_;
    @contents = grep !/^\Q$_/, @contents;
}

close(SMALL);

open(OUTPUT, ">>$output") || die ("Couldn't open the file: $output\n");

print OUTPUT @contents;
close(OUTPUT);

但是,此 Perl 脚本不会删除 Big.txt 中与 Small.txt 通用的行

在此脚本中,我首先打开大文件流并将整个内容复制到数组@contents 中。然后,我遍历小文件中的每个条目并检查它是否存在于大文件中。我从大文件中筛选行并将其保存回数组中。

我不确定为什么这个脚本不起作用?谢谢

最佳答案

你的脚本不工作因为grep使用 $_并接管(在 grep 期间)您的 $_ 的旧值来自循环(例如,您在正则表达式中使用的变量 $_ 不是用于在 while block 中存储循环值的变量 - 它们的名称相同,但作用域不同)。

改用命名变量(通常,永远不要对任何超过 1 行的代码使用 $_,正是为了避免此类错误):

while (my $line=<SMALL>) {
    chomp $line;
    @contents = grep !/^\Q$line/, @contents;
}

但是,正如 Oleg 指出的那样,更有效的解决方案是将小文件的行读入哈希,然后一次处理大文件,检查哈希内容(我也稍微改进了样式 - 请随意学习和使用 future ,使用词法文件句柄变量、3-arg 形式的打开和通过 $! 打印 IO 错误):

#! /usr/bin/perl

use strict;
use warnings;

my ($small, $big, $output) = @ARGV;

use File::Slurp;
my @small = read_file($small);
my %small = map { ($_ => 1) } @small;

open(my $big, "<", $big) or die "Can not read $big: Error: $!\n";
open(my $output, ">", $output) or die "Can not write to $output: Error: $!\n";

while(my $line=<$big>) {
    chomp $line;
    next if $small{$line}; # Skip common
    print $output "$line\n";
}

close($big);
close($output);

关于perl - 如何从 Perl 中的 2 个文件之一删除公共(public)行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10880980/

相关文章:

perl - 如何在 Vim 中有效地将行转换为列?

正则表达式以任意顺序匹配多个捕获组

regex - 试图理解这个 perl 正则表达式括号字符类?

perl - 删除哈希中某个键的重复值

javascript - 需要简单的 Perl 脚本帮助

perl - 如何按排序顺序读取目录中的文件?

perl - Chop map 的所有键(使用更少的代码)

perl - 有什么好的工具可以重构 Perl web 代码吗?

Perl - 使用 perl 脚本中的 rsync

arrays - 如何在perl中找到某个短语的行号?