如何只从其他列grep和排序值[关闭]

问题描述 投票:-2回答:4

我有一个输入file1.txt,如下所示:

file1.txt:

test 1 Vertical                                564N,
test 2 Vertical                                551N,
test 3 Hydrophone                              127N, 223D, 344D,
test 4 Hydrophone                              350D,
test 6 Hydrophone                              407D,

如何只获取第4列匹配值,然后分类如下?

Output :
N   D 
564 223 
551 344
127 350
    407
linux perl awk
4个回答
2
投票

在GNU awk中:

$ awk '
BEGIN {
    FS=",? *"                 #
    OFS="\t"                  # output fields separated by tabs
}
{
    for(i=4;i<=NF;i++)        # process fields 4 and above
        if($i~/N/)            # hash n and d accordingly
            n[++j]=$i
        else if($i~/D/)
            d[++k]=$i
}
END {
    n[j=0]="N"                # headers 
    d[k=0]="D"
    while(n[j]!=""||d[k]!="") # output them untile they run out
        print substr(n[j],1,length(n[j++]-1)),substr(d[k],1,length(d[k++]-1))
}' file

输出:

N      D
564    223
551    344
127    350
       407

1
投票

并且perl版本的输出格式与您的相同:

#!/usr/bin/perl
use warnings;
use strict;
use List::MoreUtils qw/zip/;

my %nums;
while (<>) {
  my @f = split /\s+/;
  for my $nd (@f[3..$#f]) {
    if ($nd =~ /^(\d+)([ND])/) {
      push @{$nums{$2}}, $1;
    }
  }
}
print "N   D\n";
my @pairs = zip @{$nums{N}}, @{$nums{D}};
while (@pairs) {
  my ($n, $d) = (shift @pairs, shift @pairs);
  printf "%-3s %-3s\n", $n//"", $d//"";
}

编辑:经过一些打高尔夫球和打球:

#!/usr/bin/perl
use warnings;
use strict;
use List::MoreUtils qw/zip6/;
my %nums = (N => [ "N" ], D => [ "D" ]);
while (<>) {
  my @f = split /\s+/;
  for my $nd (@f[3..$#f]) {
    push @{$nums{$2}}, $1 if $nd =~ m/^(\d+)([ND])/;
  }
}
printf "%-3s %-3s\n", $_->[0]//"", $_->[1]//"" for zip6 @{$nums{N}}, @{$nums{D}};

0
投票

这是一个Perl解决方案

读取输入文件,并从每一行中丢弃前三列。剩下的是搜索看起来像999N999D的字段,它们被分成数组的散列,其中ND作为其键

对数组进行排序后,它们将显示为适当标题下方的列

use strict;
use warnings 'all';
use List::Util 'max';

open my $fh, '<', 'file1.txt' or die $!;

my %data;

while ( <$fh> ) {
    my @fields = split ' ', $_, 4;
    push @{ $data{$2} }, $1 while $fields[3] =~ /(\d+)([ND])/g;
}

$_ = [ sort { $a <=> $b } @$_ ] for values %data;

my $last = max map $#$_, values %data;

my $fmt = "%-3s %-3s\n";
printf $fmt, qw/ N D /;
for my $i ( 0 .. $last ) {
    printf $fmt, map { $_->[$i] // '' } @data{qw/ N D /};
}

output

N   D  
127 223
551 344
564 350
    407

-1
投票

这应该有所帮助。

Python code

from itertools import izip_longest
#Python3
#from itertools import zip_longest

N = []
D = []
with open(filename) as infile:
    for line in infile:                   #Iterate Each line
        val = line.split()[3:]            #Get Required value using slicing
        for i in val:
            if i.endswith("N,"):
                N.append(int(i.rstrip("N,")))
            else:
                D.append(int(i.rstrip("D,")))

for i in izip_longest(sorted(N, reverse=True), sorted(D), fillvalue=""):    #Sort and iterate. 
    print(i)

Output

564, 223
551, 344
127, 350
'', 407
© www.soinside.com 2019 - 2024. All rights reserved.