2017-04-03 95 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文件