Sed 基于第一行返回多行,其中包含来自第二个文件的查询
我有一个大文件(~4000000行),由多个数据块组成,每个数据块都有一个介绍性的ID标记,第二个文件中有一个选定的ID标记列表 例如: Data.txtSed 基于第一行返回多行,其中包含来自第二个文件的查询,sed,Sed,我有一个大文件(~4000000行),由多个数据块组成,每个数据块都有一个介绍性的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.tx
>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_Tags.txt中指定数据的ID标记和相应数据,这样我就会得到一个如下所示的文件:
选择_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标记。有没有办法避免手动执行此操作?您可以使用以下
awk
脚本:
awk 'NR==FNR{i[$1];next} NF>1 && $1 in i{print ">"$0}' RS='>' ids.txt data.txt
输出:
>ID:1000
这方面的数据
更多数据
数据
>身份证号码:1002
等
我的解决方案的关键是使用RS='>'
将默认的记录分隔符\n
替换为
。使用此技巧访问数据的各个字段非常简单
解释
我们正在将这两个文件传递给awk、ids.txt和data.txt,awk将按顺序处理它们
NR==FNR{i[$1];next}
运行,除非awk正在解析第一个文件ids.txtNR
表示当前记录编号,FNR
表示当前文件中记录的编号。它们仅在解析第一个文件时相等i[$1]
添加id值(不带前导的
,因为它是字段分隔符)作为数组i
的键<代码>下一步停止该行的进一步处理
$1 in i{print”>“$0}
将检查数据记录的第一列(id)是否是数组i
中的键,并在将
添加回该记录的前面时打印该记录
请注意,我们正在另外检查NF>1
(表示记录不是空的),因为awk将返回一个空的第一条记录,因为数据文件以记录分隔符
开头<数组中的code>将在awk中生成true
,并将打印和附加
这可能适合您(GNU-sed):
这将从ids文件构建一个sed脚本,并针对数据文件运行该脚本。sed脚本在ids文件中查找这些id,并打印id行和后面的那些行,直到下一个id返回并检查id。所有其他行都将被删除。谢谢,现在应该修复。通常,您应该测试
NF
,而不是$0
,决定记录是否为空,因为如果存在值且数值计算结果为零,则对$0
的测试将失败。在这种情况下,我看不出$0
如何不希望地计算为零,因为每个记录都以ID
开头,但这只是一般的经验法则。当然,在这种情况下,测试NR>1
会更清晰。@EdMorton谢谢Ed,我一直很感谢您的演讲!:)实际上,我建议单独使用NF
(测试一条空记录)或NR>1
(测试第二条和后续记录),而不是NF>1
(测试记录中的多个字段)。那些清晨的讲座很难集中注意力,我想:-)。虽然我已经想到了,但你的讲座看起来干净多了。加1。不客气。如果/当您准备接受答案时,请记住单击答案旁边的复选标记。
$ awk 'NR==FNR{tags[$0];next} /^>/{f=($0 in tags)} f' ID_Tags.txt Data.txt
>ID:1000
data about this
more data
data
>ID:1002
foo
$ awk 'NR==FNR{tags[$0];next} /^>/{f=($0 in tags)} f' ID_Tags.txt Data.txt
>ID:1000
data about this
more data
data
>ID:1002
foo