基于第一行返回多行以及来自第二个文件的查询

时间:2015-06-24 21:02:49

标签: sed

我有一个大文件(~4,000,000行),由多个数据块组成,每个数据块都有一个介绍性ID标记,以及第二个文件中选定ID标记的列表。

例如:

DATA.TXT

>ID:1000
data about this
more data
data
>ID:1001
blah blah
data
>ID:1002
foo
...

和ID_Tags.txt

>ID:1000
>ID:1002
>ID:1085
>ID:3062
...

我需要一种方法从Data.txt中获取ID标签和相应数据,以获取ID_Tags.txt中指定的数据,这样我最终得到的文件如下:

Select_Data.txt

>ID:1000
data about this
more data
data
>ID:1002
foo
...

我可以使用

一次获得一个数据块
sed -n '/ID:1000/,/>/p' Data.txt | head -n -1 >> Select_Data.txt

但是这一次只能做一个ID标签,而且我有数百个选择ID标签。有没有办法避免手动执行此操作?

3 个答案:

答案 0 :(得分:2)

data

答案 1 :(得分:0)

您可以使用以下awk脚本:

awk 'NR==FNR{i[$1];next} NF>1 && $1 in i{print ">"$0}' RS='>' ids.txt data.txt

输出:

>ID:1000
data about this
more data
data
>ID:1002
etc

我的解决方案的关键是使用\n替换>之前的默认记录分隔符RS='>'。使用这个技巧,访问数据的各个字段非常简单。

<强>解释

我们将这两个文件传递给awk, ids.txt data.txt ,然后awk将按顺序处理它们。

除非awk正在解析第一个文件 ids.txt ,否则

NR==FNR{i[$1];next}会运行。 NR表示当前记录号,FNR表示当前文件中的记录号。它们仅在解析第一个文件时相同。 i[$1]将id的值(不包括前导>,因为它是字段分隔符)添加为数组i的键。 next停止进一步处理该行。

$1 in i {print ">"$0}将检查数据记录的第一列(id)是否为数组i中的键,并在将>添加回前面时打印记录它

请注意,我们还检查NF>1(意味着记录是否为空),因为awk将返回空的第一条记录,因为数据文件以记录分隔符>开头。 <none> in array会在awk中生成true,并会打印并添加>

答案 2 :(得分:0)

这可能适合你(GNU sed):

  sed $'1i:a\ns#.*#/^&$/bb#;$ad;:b;n;/^>/ba;bb' ids_file | sed -f - data_file

这将从ids文件构建一个sed脚本,并针对数据文件运行脚本。 sed脚本在ids文件中查找这些ID并打印id行和后面的行,直到它循环的下一个id检查id。所有其他行都将被删除。