将列表中的子字符串与另一个文件中的多个列匹配

时间:2017-04-14 04:46:33

标签: perl unix text-processing

我是linux和perl编程的新手。我已经用尽所有搜索选项但没有回答。 我有一个主文件“master.txt”,其中包含已知2列的所有交互,其中已知同一行上的项目将进行交互。我有一个项目列表“list.txt”,我希望它是从主文件返回结果的搜索条件,如果它包含在第1列和第2列中。所有文件都是制表符分隔的。例如: 如果这是主文件:“master.txt”

AppleP001   BallP002
AppleP002   CatP001 
BallP001    DogP001
BallP002    AppleP001
CatP001 AppleP002
DogP001 BallP001
DogP002 ZebraP001
ElephantP001    CardinalP001
FishP001    AntelopeP001

此搜索文件:“list.txt”

Apple
Ball
Cat
Dog

生成的文件在两列上只应包含Apple *,Ball *,Cat *和Dog *,但删除重复的项目:

我尝试使用grep:

grep -f list.txt master.txt > Sub_list.txt

但我明白了:

AppleP001       BallP002
AppleP002       CatP001
BallP001        DogP001
BallP002        AppleP001
CatP001 AppleP002
DogP001 BallP001
DogP002 ZebraP001

如何删除重复项(如果两个项目位于同一行,并认为它们所在的列无关紧要,请将其视为重复项)并从输出文件中删除不相关的数据并获取此项?

AppleP001   BallP002
AppleP002   CatP001 
BallP001    DogP001 

非常感谢任何帮助!感谢。

2 个答案:

答案 0 :(得分:1)

如果文件非常大但是没有提到

那么有点重
use warnings;
use strict;
use feature 'say';
use Path::Tiny;
use List::Util qw(uniq any all);

my ($file, $flist) = ('master.txt', 'list.txt'); 

my @search = path($flist)->lines({ chomp => 1 });

# Sort words within each line so then filter out duplicate lines
my @filtered = uniq map { join ' ', sort split } path($file)->lines;

# Each word on the line needs to match a word in @search list
my @result = grep { all { found($_, \@search) } split } @filtered;

say for @result;

sub found { return any { $_[0] =~ /^$_/ } @{$_[1]} }

输出符合我对问题描述的理解

AppleP001 BallP002
AppleP002 CatP001
BallP001 DogP001

如果由于某种原因你无法Path::Tiny提供path,请打开文件并检查,而不是path(...)->lines读取文件句柄(所以在列表上下文中)和做chomp @search;

最后一部分,写了一点

# Each word on the line needs to match a word in @search list
my @result = grep { 
    my ($w1, $w2) = split; 
    any { $w1 =~ /^$_/ } @search  and  any { $w2 =~ /^$_/ } @search;
} @filtered;

答案 1 :(得分:0)

这是awk中的一个:

$ awk '
NR==FNR { a[$1]; next }    # read list and hash to a
{                          # process master
    b=""                   # reset buffer
    for(i in a)            # iterate thru a
        if(index($0,i)) {  # if list item is found in current master record
            b=$0           # set the record to buffer
            delete a[i]    # remove list entry from a
        }
        if(b) print b      # print b
}' list master             # mind the order
AppleP001   BallP002
AppleP002   CatP001 
BallP001    DogP001