抓住两列之间的所有匹配项

时间:2019-01-24 16:45:16

标签: awk append match

我有两个文件,我想比较它们的1st columns并将2nd column的{​​{1}}附加到file2.txt的末尾,除非存在匹配项:

file1.txt

我正在尝试下面的代码-我希望它可以工作-:

file1.txt
NC_000008.10    1264       5646      G_synym=E4566
NC_000008.10    1264       5646      G=AGO2
NC_000008.10    5584       5646      G=AGO2
NC_000008.10    5218       5410      G=AGO2
NC_000008.10    2911       3031      G=AGO2
NC_000008.10    2552       2733      G=AGO2
NC_000008.10    0473       0609      G=AGO2
NC_000008.10    9494       9628      G=AGO2
NC_000008.10    8584       8671      G=AGO2
NC_000008.10    7188       7335      G=AGO2


file2.txt
NC_000001.10    chr1
NC_000002.11    chr2
NC_000003.11    chr3
NC_000004.11    chr4
NC_000005.9     chr5
NC_000006.11    chr6
NC_000007.13    chr7
NC_000008.10    chr8
NC_000009.11    chr9
NC_000010.10    chr1 

给出以下输出:

awk 'NR==FNR { a[$1] = $0; next }($1) in a { print a[$1], $2 }' file1.txt file2.txt

它只是随机打印其中一项匹配项。

但是预期的输出将是:

NC_000008.10    7188       7335      G=AGO2 chr8

如何使NC_000008.10 1264 5646 G_synym=E4566 chr8 NC_000008.10 1264 5646 G=AGO2 chr8 NC_000008.10 5584 5646 G=AGO2 chr8 NC_000008.10 5218 5410 G=AGO2 chr8 NC_000008.10 2911 3031 G=AGO2 chr8 NC_000008.10 2552 2733 G=AGO2 chr8 NC_000008.10 0473 0609 G=AGO2 chr8 NC_000008.10 9494 9628 G=AGO2 chr8 NC_000008.10 8584 8671 G=AGO2 chr8 NC_000008.10 7188 7335 G=AGO2 chr8 打印所有匹配项而不是仅打印所有匹配项?

3 个答案:

答案 0 :(得分:2)

您应该在Awk中使用的代码已经

awk 'FNR == NR { hash[$1] = $2; next } $1 in hash { NF++; $NF = hash[$1] }1' file2 file1

想法是在file2上,我们将第一列中的值与第二个中的值进行哈希运算。在遍历file1时,为了匹配哈希索引中的值,我们引入了一个新列来存储哈希值。 NF++基本上将文件中的列数增加一,因为我们引入了包含哈希值的新列。

要生成更格式化的命令输出,请将输出分隔符设置到选项卡OFS="\t"或使用column命令,即,将awk的结果传递给column -t

答案 1 :(得分:2)

如果文件在密钥中排序,最简单的是

$ join -a1 file1 file2 | column -t

NC_000008.10  1264  5646  G_synym=E4566  chr8
NC_000008.10  1264  5646  G=AGO2         chr8
NC_000008.10  5584  5646  G=AGO2         chr8
NC_000008.10  5218  5410  G=AGO2         chr8
NC_000008.10  2911  3031  G=AGO2         chr8
NC_000008.10  2552  2733  G=AGO2         chr8
NC_000008.10  0473  0609  G=AGO2         chr8
NC_000008.10  9494  9628  G=AGO2         chr8
NC_000008.10  8584  8671  G=AGO2         chr8
NC_000008.10  7188  7335  G=AGO2         chr8

column -t仅用于精美格式。 a1将打印第一个文件中不匹配的记录。

答案 2 :(得分:1)

请尝试以下操作:

const handlers = asHandlerMap({
  "number/append": numberReducer,
  "dog/walk": dogWalkReducer
}); // okay, handlers is of type HandlerMap<NumberAppendAction | DogWalkAction>

您应该先阅读file2,然后阅读file1。

但是,在您的问题中有些模棱两可,您没有说是否应该打印awk 'NR==FNR{a[$1]=$2;next}$1 in a{$(++NF)=a[$1]}1' file2.txt file1.txt 行。
如果您不希望这些行不匹配,那么:

not matched

另一件事是,输出字段用单个空格分隔。由于输入文件的格式似乎不错,因此您可能想awk 'NR==FNR{a[$1]=$2;next}$1 in a{$(++NF)=a[$1];print}' file2.txt file1.txt -v OFS="\t"分隔输出。

请注意,如果file2可以为空,则应将TAB更改为其他文件检查方法,例如GNU awk的NR==FNRARGIND==1FILENAME=="file2.txt"等。

FILENAME==ARGV[1]检查文件,这基本上是第一个读取文件(此处为NR==FNR)。
file2.txt是用于存储file1.txt第二行的数组,使用第一行作为键。
a看看$1 in a是否存在于数组$1中作为键,如果存在则表示匹配。 (如果要改为检查该值,则可以更改为a。当您确定该值不会为空时,可以互换使用它们。)
a[$1]将字段号增加1。++NF代表最后一列。所以
$NF代表$(++NF)最后一列之后的列。
最后裸露的file2.txt只是一个简单的1,暗示着true块。