【问题标题】:How to merge files based on a common column?如何基于公共列合并文件?
【发布时间】:2020-01-07 02:41:34
【问题描述】:

有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,它作为命令行工作,但在bash 和sh 中都失败了。而且它不匹配,它只是复制粘贴。

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

【问题讨论】:

  • 我尝试加入,但加入在我的 shell 中出现错误 - 你是如何尝试的?
  • 您的awk 尝试正确:awk 'NR==FNR {h[gensub(",","",1,$1)] = $2; next} {print $0,h[$7]}' file2 file1

标签: linux bash shell perl


【解决方案1】:

使用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 位,但您仍需要从第二个文件中删除逗号。

【讨论】:

    【解决方案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
    }
    

    如果您想从命令行获取文件名,请将file1 和file2 替换为$ARGV[0] 和$ARGV[1]。我不知道/usr/bin/parse 和awk 是否可以像您建议的那样在这种情况下工作。看看如何会很有趣。在大多数情况下,Perl 优于 awk。

    【讨论】:

    • 嗨 Kjetli,非常感谢您的及时回答,我将上述解决方案作为 .sh 文件运行,但出现以下错误,我的 shell 是 bash。 test.sh:第 1 行:意外标记附近的语法错误 (' test.sh: line 1: my %h = split/[, \n]+/, qx(cat file2);'
    • @Novice 我现在将#!/usr/bin/perl 添加为第一行。例如,将我的答案保存到merge.pl 和chmod +x merge.pl。现在您应该可以运行:./merge.pl,如果这不起作用,请运行:perl merge.pl。 (三个文件都应该在当前目录下:merge.pl、file1 和 file2)
    【解决方案3】:

    可以使用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 视为分隔符

    【讨论】:

    • 非常感谢@Xiawi,它为我所用。
    【解决方案4】:

    将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;
      }
    }
    

    【讨论】:

      【解决方案5】:

      请尝试以下方法:

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

      结果:

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2014-07-12
        • 2016-01-16
        • 1970-01-01
        • 2021-09-02
        相关资源
        最近更新 更多