2017-04-03 91 views
0

我有三列,像这样多的ASCII输入数据文件:折射率匹配多个文件

文件1:

00005 3 a 
00005 17 b 
00007 20 c 
00009 2 d 
00042 4 e 
00042 37 f 
00090 49 g 

文件2:

00005 3 A 
00005 17 B 
00009 2 C 
00007 20 D 
00042 4 E 
00090 49 F 
00042 37 G 

文件3:

00005 3 100 
00009 2 200 
00007 20 300 
00090 49 400 
00042 37 500 

前两列起作用像索引,第三列是数据属性。从我的示例文件中可以看出,前两列不必以任何顺序排列,某些文件中可能缺少一些索引。我想比较这三个文件,并有像这样的输出:

输出1(合并数据):

00005 3 a A 100 
00007 20 c D 300 
00009 2 d C 200 
00042 37 f G 500 
00090 49 g F 400 

输出2(指数数据不完整):

00005 17 
00042 4 

我目前(和马虎)解决方案涉及查找最多行的文件,从中获取索引,查找其他文件中的索引并打印这些文件:

我的解决方案:

cat file1 | while read line 
do 
    index1=$(echo $line | awk '{print $1}') 
    index2=$(echo $line | awk '{print $2}') 
    attribute1=$(echo $line | awk '{print $3}') 
    attribute2=$(grep "^"$index1" "$index2" " file2 | awk '{print $3}') 
    attribute3=$(grep "^"$index1" "$index2" " file3 | awk '{print $3}') 
    echo $index1 $index2 $attribute1 $attribute2 $attribute3 
done > output 

然而,这会给我一个输出文件与输出看起来像“洞”:

输出:

00005 3 a A 100 
00005 17 b B 
00007 20 c D 300 
00009 2 d C 200 
00042 4 e E 
00042 37 f G 500 
00090 49 g F 400 

我仍然可以找到很好的数据,并通过使用丢失的数据awk(分别为NF == 3和NF < 3),但我觉得应该有一个更清洁(也可能更快)的方法,因为我觉得我的解决方案很慢并且容易出错(特别是grep find) 。

回答

0

awk来救援!

,如果你不能对文件进行排序,这里是一个解决方案

awk     '{k=$1 FS $2} 
    FILENAME==ARGV[1] {a[k]=$3; next} 
    FILENAME==ARGV[2] {b[k]=$3; next} 
        {c[k]=$3} 
(k in a) && (k in b) {print k,a[k],b[k],c[k] > "output1.txt"} 
         delete a[k]; delete b[k]; delete c[k]} 
    END    {for(k in a) d[k]; 
         for(k in b) d[k]; 
         for(k in c) d[k]; 
         for(k in d) print k > "output2.txt"}' file{1..3} 

UPDATE首先解决方案并不总是最好的,有太多的代码重复,而不是一般的不够。下面的一个更好,但不一定更短。但可以扩展到更多数量的文件。

awk '{k=$1 FS $2} 
    {for(i=1;i<ARGC;i++) 
     if(FILENAME==ARGV[i]) 
      {a[k,i]=$3; c[k]++}} 
END {f="output1.txt"; 
     for(k in c) 
     if(c[k]==ARGC-1) 
      {printf "%s", k > f; 
      for(i=1;i<=c[k];i++) printf "%s", OFS a[k,i] > f; 
      print "" > f} 
     else print k > "output2.txt"}' file{1..3} 
+0

谢谢!我会测试玩这个。我不知道你可以打开并从多个文件中读取以及在awk中存储值。 – Ben

0

的awk和bash既可以做到这一点,当然,谈论列:)当AWK是一个容易得多

AWK:

#!/usr/bin/awk -f 

{ 
    arr[$1][$2] = arr[$1][$2] (arr[$1][$2]?" ":"") $3 
} 
END{ 
    while(c++ < 2) 
    { 
     if(c == 1) 
     { 
      print "Combined values" 
      reg = /[0-9]$/ 
     } 
     else 
     { 
      print "Incomplete values" 
      reg = /[A-Z]$/ 
     } 

     for(i in arr) 
      for(j in arr[i]) 
       if(arr[i][j] ~ reg) 
        print i,j,arr[i][j] 
    } 
} 

庆典(4+):

#!/usr/bin/env bash 

declare -A arr 

for file 
do 
    while read -r i1 i2 v 
    do 
     arr[$i1$i2]="${arr[$i1$i2]}$([[ -n ${arr[$i1$i2]} ]] && echo -n " ")$v" 
    done<"$file" 
done 

for i in 1 2 
do 
    if ((i == 1)) 
    then 
     vals="Combined values" 
     reg='[0-9]$' 
    else 
     vals="Incomplete values" 
     reg='[A-Z]$' 
    fi 

    echo "$vals" 

    for idx in "${!arr[@]}" 
    do 
     [[ "${arr[$idx]}" =~ $reg ]] && echo "${idx:0:5} ${idx:5} ${arr[$idx]}" 
    done | column -t 
done 

您可以通过以下方式调用: - ./script_name文件