AWK,字符串匹配并替换

时间:2016-05-02 18:40:49

标签: awk sed

我有两个文件;第一个看起来像这样,

        SomeFile.CEL    SomeOtherFile.CEL
probe1  111     666
probe2  222     777
probe3  333     888
probe4  444     999
probe5  555     100
probe6  101     102

,第二个看起来像这样(注意:重复的probe4,有两个不同的基因名称),

probe1  Gene1
probe2  Gene2
probe3  Gene3
probe4  Gene4A
probe4  Gene4B
probe5  Gene5
probe7  Gene6

我需要的是一个看起来像这样的输出文件,

Gene1 111 666
Gene2 222 777
Gene3 333 888
Gene4A 444 999
Gene4B 444 999
Gene5 555 100

这个理想的输出文件将包含两个文件之间匹配探针名称的所有基因名称。另外,如果单个探针存在多个名称,我希望对所有可能的基因名称复制表达数据(444 999)(此示例显示单个探针的2个基因名称,但可能多达5或6个。) 顺便说一下,所有文件都是以制表符分隔的。

我已经搜索了这个和其他论坛,而这些文章接近了,

Replace multiple arguments with gsub

awk print column $3 if $2==a specific value?

awk partly string match (if column partly matches)

Sed pattern to match and replace

Regex match and replace

他们没有回答我的完整问题。

到目前为止,我用这个命令取得了最大的成功,

awk -F"\t" 'FILENAME=="input1.file"{a[$1]=$1} FILENAME=="input2.file {if(a[$1]){$1="";print $0}}'   input1.file input2.file

但它没有说明必要的重复。最后,有些文件看起来像input1,但不仅包含我描述的两个样本(someFile.CEL和someOtherFile.CEL)。可能有多达50个样本/ CEL文件。我想我可能要编写一个脚本,但我想我先问一下是否有更简单的方法。

3 个答案:

答案 0 :(得分:2)

$ awk 'NR==FNR{a[$1]=$2 FS $3; next} $1 in a{print $2, a[$1]}' file1 file2
Gene1 111 666
Gene2 222 777
Gene3 333 888
Gene4A 444 999
Gene4B 444 999
Gene5 555 100

答案 1 :(得分:1)

有一个不太知名的unix工具用于连接(已排序)公共列上的文件,称为join。您可以在这种情况下使用它:

join <( sort file2.txt) <(sort file1.txt ) | cut -d\  -f2-
  • 非排序文件需要sort
  • cut需要使用探测名称
  • 去除第一列
  • 由于分类和切割,awk可能更快

答案 2 :(得分:1)

join GNU命令是针对这种情况制作的,可以与awk结合使用。

这一个班轮版本在第一个文件中使用任意数量的列(FIELDS):

 join SomeFile.CEL SomeOtherFile.CEL | awk '{$1=$NF; $NF=""; print}'

默认情况下,两个文件的第一个FIELD用于JOIN

必须在连接字段中对2个文件进行排序。

另外2个sort的测试,以确保对JOIN字段进行排序:

$ join <(sort SomeFile.CEL) <(sort SomeOtherFile.CEL) | awk '{$1=$NF; $NF=""; print}'
Gene1 111 666
Gene2 222 777
Gene3 333 888
Gene4A 444 999
Gene4B 444 999
Gene5 555 100

使用另一个包含更多列的第一个文件进行第二次测试:

$ cat SomeFile_ManyColumns.CEL
probe1  111     666 666    111 777 888 999
probe2  222     777 111    666 999 888 777
probe3  333     888 101    102 999 888 111
probe4  444     999 876    543 321 678 101
probe5  555     100 101    543 321 666 999
probe6  101     102 888    321 543 101 678

$ join <(sort SomeFile_ManyColumns.CEL) <(sort SomeOtherFile.CEL) | awk '{$1=$NF; $NF=""; print}'
Gene1 111 666 666 111 777 888 999
Gene2 222 777 111 666 999 888 777
Gene3 333 888 101 102 999 888 111
Gene4A 444 999 876 543 321 678 101
Gene4B 444 999 876 543 321 678 101
Gene5 555 100 101 543 321 666 999

----

对于历史记录,具有固定列数(FIELDS)的解决方案:

join -o 2.2,1.2,1.3 SomeFile.CEL SomeOtherFile.CEL

-o 2.2,1.2,1.3指定输出FORMAT:它是一个或多个逗号或空白分隔的规范,每个都是`FILENUM.FIELD&#39;

测试:

$ join -o 2.2,1.2,1.3 SomeFile.CEL SomeOtherFile.CEL
Gene1 111 666
Gene2 222 777
Gene3 333 888
Gene4A 444 999
Gene4B 444 999
Gene5 555 100