如何阅读内容文件,执行一些说明,然后逐行将所有有趣的内容复制到另一个文件?

时间:2014-06-05 10:57:04

标签: perl file-io

文件1:

1. "a:1 b c:10 d e f g:2 a:1 a:1 a:1"
2. "h i l m"
3. "e:1 b"
4. "f:2 e:5 a"

文件2应为

1. "a:1 c:10 g:2"
2. "f:2 e:5"

所以我想:

  1. 在重复元素的情况下只保存一个样本(例如第1行和第34行; a:1"),
  2. 检查该行是否包含我想要保存的元素(因此必须是ex。" a:1"而不仅仅是" a")
  3. 如果只有一个有趣的元素(第3行),我将不评估该行。
  4. 我试图在一段时间内将文件内容放入一个数组中但是当我打印出我的内容时,它全部打印在第一行。

    这是我的尝试:

    use List::MoreUtils qw(uniq);
    
    $in = "in.txt";
    $out = "out.txt";
    
    open (IN, "<", $in);
    open (OUT, ">", $out);
    
    while(defined ( $l = <IN>)){
        @a = split (/\s/, $l);
        @c= uniq(@a);
        for ($i = 0; $i < @c; $i++){
            if ($c[$i] =~ /.*:-?\d\.\d+/) {
                print OUT $c[$i];   
            }
        }
    
    }
    

4 个答案:

答案 0 :(得分:3)

这将按照你的要求行事。

目前还不清楚行号和引号是否属于您的数据,但我已经写好了,因此无论哪种方式都不重要

程序期望输入文件的路径作为命令行上的参数

use strict;
use warnings;

while (<>) {
  my %seen;
  my @wanted = grep { /:/ and not $seen{$_}++ } /[^\s"]+/g;
  print "@wanted\n" if @wanted > 1;
}

<强>输出

a:1 c:10 g:2
f:2 e:5

答案 1 :(得分:1)

这是你可以做到的一种方式:

#!/usr/bin/env perl

use strict;
use warnings;

my $i = 1;    
while (<>) {
    my %h;                            # create an empty hash every line
    foreach (split /["\s]/) {         # split on double quotes and spaces
        $h{$_}++ if /:/;              # if colon found, add element to hash
    }
    if (keys %h > 1) {                # if more than one element in hash
        print (($i++), q/. "/, (join " ", (keys %h)),  qq/"\n/);
    }
}

用法:file.pl in.txt > out.txt

我不确定包含该行的确切标准是什么,但上述代码适用于您的示例数据。因为正在使用散列,所以内容不一定是正确的顺序。如果你想sort这些值,那将是一个小修改。

输出:

1. "c:10 a:1 g:2"
2. "f:2 e:5"

答案 2 :(得分:1)

这个丑陋的单行也使用哈希,但保留了字段的顺序。

perl -ne '
  %h=(); 
  print qq($nr. "$_"\n) 
    if $_=join " ", grep !$h{$_}++, /\w+:\d+/g and / / and ++$nr
' in.txt > out.txt 

输出:

1. "a:1 c:10 g:2"
2. "f:2 e:5"

答案 3 :(得分:0)

我有点玩这个问题很有趣。

这可能对你帮助不大,因为阅读起来有点棘手,但这就是我最终的结果:

use List::MoreUtils qw(uniq);
$in = "in.txt";
$out = "out.txt";

open (IN, "<", $in);
open (OUT, ">", $out);

foreach (<IN>) {
   @result =  map /.\:\d*/ ? $_ : (), uniq ( split ) ;
   print OUT join(" ", @result) . "\n" unless ($#result < 1);
}

输出:

a:1 c:10 g:2
f:2 e:5

这是一个不使用uniq的版本,并使用-n选项来处理while循环。

#!/usr/bin/perl -n
my %seen;
@result =  map /.\:\d*/ ? $_ : (), grep {! $seen{$_}++ } ( split ) ;
print join(" ", @result) . "\n" unless ($#result < 1);

输出:

./myscript.pl in.txt
a:1 c:10 g:2
f:2 e:5

我只是注意到如果只有一个结果就不应该打印 通过更改$#结果测试很容易解决。