我有一个大文件(~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标签。有没有办法避免手动执行此操作?
答案 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。所有其他行都将被删除。