根据其他文件更改文件信息

时间:2014-10-02 18:10:43

标签: shell awk sed grep

我有两个简单的文本文件:

第一个参考文件看起来像这样 - 每一行的第一个字母都是重要的一个。

G A
C A
G A

第二个看起来像这样:

G G G G
A A A A
A A A G

第二个文件是我想要根据第一个文件的信息更改的文件。

例如,如果前两列包含字母G,即G G,因为此字母是我的参考文件中的第一个字母,我想将这两个列转换为带有该数字的单个列2(表示有两个G)。第三列和第四列也有两个G,因此我想将这两列也转换为数字为2的单个列。

在第二个文件的最后一行中,前两列的字母为AA,但因为我的参考文件最后一行的第一个字母是{{1}我想将这两列转换为数字0(表示零G - 参考文件的第一个字母是我正在计算的那个字母)。第三列和第四列有一个G和一个A,因为有一个G,我希望将这两列转换为一个数字为1的列。

转换后的文件应如下所示:

G

任何帮助将不胜感激。一次处理两个文件并进行此类转换不在我的编程技能范围内。

注意:我的真实文件包含字母A,C,G和T

1 个答案:

答案 0 :(得分:0)

假设第一个文件名为ref,第二个文件名为data

$ awk 'NR==FNR{a[FNR]=$1; next} {print (a[FNR]==$1)+(a[FNR]==$2), (a[FNR]==$3)+(a[FNR]==$4)}' ref data
2 2
0 0
0 1

说明:

  • NR==FNR{a[FNR]=$1; next}

    NR是到目前为止已读取的行数,FNR是到目前为止从当前文件读取的行数。因此,当NR==FNR时,我们知道awk仍在处理第一个文件。在这种情况下,我们将第一个字母保存在数组a中的行上。 next语句告诉awk跳过其余命令并转到下一行。

  • print (a[FNR]==$1)+(a[FNR]==$2), (a[FNR]==$3)+(a[FNR]==$4)

    由于上面的next命令,只有在我们处理第二个文件时才会执行此命令。如果是这样,我们打印出前两列中有多少字母与ref文件中相应行的第一个字母匹配,然后对第三列和第四列执行相同操作。

处理缺失的数据

假设0 0表示缺失数据。例如,获取此数据文件:

$ cat data2
G G G G
0 0 C A
A G 0 0

以下awk脚本已扩展为显示“?”数据丢失的地方:

$ awk 'NR==FNR{a[FNR]=$1; next} {print ($1==0)?"?":(a[FNR]==$1)+(a[FNR]==$2), ($3==0)?"?":(a[FNR]==$3)+(a[FNR]==$4)}' ref data2
2 2
? 1
1 ?

(与以前一样使用了相同的ref文件。)

处理任意数量的列

awk 'NR==FNR{a[FNR]=$1; next} {s="";for (i=1;i<NF;i=i+2) {s=s OFS (($i==0)?"?":((a[FNR]==$i)+(a[FNR]==$(i+1))))}; print s}' ref3 data3