如何基于公共列合并文件?

时间:2019-09-04 08:27:06

标签: linux bash shell perl

有2个文件,file1是telnet命令的输出,即

25-08-2019 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ]  
25-08-2019 : Port port2 of URL http://ip2:port2/ is [ NOT OPEN ] 

另一个是file2,就像

http://ip1:port1/, ZOOM1  
http://ip2:port2/, ZOOM2  
http://ip3:port3/, ZOOM3

我需要根据通用IP和端口合并这两个文件。输出应为第三个文件,例如:

25-08-2019 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ]  ZOOM1  
25-08-2019 : Port port2 of URL http://ip2:port2/ is [ NOT OPEN ]  ZOOM2

我尝试了join,但是join在我的shell中给出了错误。 没有 join的任何帮助将非常有帮助。

我尝试了join,它可以作为命令行使用,但是在bashsh中的Shell脚本中均失败。此外,它不匹配,只是复制粘贴。

paste -d " : " file1 <(cut -s -d ',' -f2 file2)

我也尝试了awk命令,但是它不能按预期处理文件。

awk 'NR==FNR {h[$2] = $3; next} {print $1,$2,$3,h[$2]}' file2 file1 > file3

5 个答案:

答案 0 :(得分:3)

使用join有点复杂,因为两个文件具有不同的分隔符,但是:

$ join -17 -21 -o 1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.10,1.11,1.12,2.2 <(sort -k7,7 a.txt) <(sort -k1,1 -t, b.txt | tr -d ',')
25-08-2019 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ] ZOOM1
25-08-2019 : Port port2 of URL http://ip2:port2/ is [ NOT OPEN ] ZOOM2

如果文件已经根据URL进行了排序,则sort位可以删除,尽管您仍然需要从第二个文件中删除逗号。

答案 1 :(得分:2)

#!/usr/bin/perl
my %z = split/[, \n]+/, qx(cat file2);  # read file2 into %z for lookups
my @file1 = split/\n/, qx(cat file1);   # read lines of file1 into @file1
for( @file1 ){                          # for each line of file1
  /http\S+/;                     # find the url, \S+ is non-space chars
  print "$_ $z{$&}\n";           # url in $& print the line and "the zoom" from %z
}

如果要从命令行获取文件名,请用file1file2替换$ARGV[0]$ARGV[1]。我不知道/usr/bin/parseawk是否可以按照您的建议在这种情况下工作。看看如何会很有趣。在大多数情况下,Perl优于awk。

答案 2 :(得分:1)

可以用awk完成,但是在两个文件中使用相同的分隔符会更容易。因此,请首先删除file2中的逗号:

sed -i.old 's/,//' file2

您可以处理:

awk '{

    if(FILENAME=="file1"){
        m[$7]=$0
    }
    else {
        if(m[$1]!=""){
           print m[$1],$2
        }
    }
}' file1 file2

它首先将file1的内容注册到映射中,并在http://...上有一个键,并包含一个包含整行($0)的值。然后,它处理file2并显示如果file2的第二列对应于地图的键。

在您的特定情况下,您可以使用以下命令在一行中完成所有操作:

awk -F'[ ,]' '{

    if(FILENAME=="file1"){
        m[$7]=$0
    }
    else {
        if(m[$1]!=""){
           print m[$1],$2
        }
    }
}' file1 file2

awk将空格和逗号都视为分隔符

答案 3 :(得分:1)

file2读入哈希,然后一次处理file1一行,提取密钥并在哈希中查找。像这样:

#!/usr/bin/perl

use strict;
use warnings;

open my $fh2, '<', 'file2' or die $!;

my %data_hash = map { split /,/ } <$fh2>;

close $fh2;

open my $fh1, '<', 'file1' or die $!;

while (<$fh1>) {
  if (my ($key) = /\b(http:\S+)/) {
    if (exists $data_hash{$key}) {
      chomp;
      print "$_ $data_hash{$key}";
    } else {
      # Key doesn't exist in file2
      print;
    }
  } else {
    # No http key found on a line in file1
    print;
  }
}

答案 4 :(得分:1)

请尝试以下操作:

<?xml version="1.0" standalone="no" ?>
<svg width="100" height="100">
  <style>
    circle.semiCircle1 {
      stroke-dasharray: calc( (2 * (22/7) * attr(r)) / 2 ); /* 44 */
    }
    circle.semiCircle2 {
      stroke-dasharray: 44;
    }
  </style>
  <circle class="semiCircle1" cx="25" cy="50" r="14" stroke-width="3" stroke="#000" fill="transparent" />
  <circle class="semiCircle2" cx="75" cy="50" r="14" stroke-width="3" stroke="#000" fill="transparent" />
</svg>

结果:

awk 'NR==FNR {h[$1]=$2; next} {print $0" "h[$7]}' <(sed "s/,//" file2) file1