从基于前缀的文件中提取行

我需要从file2中提取所有以file1中包含的id#前缀开头的行。

文件1是单列,如:

324 399 408 135236 321590 

文件2是多列的,如:

 1 [tab] 108 [tab] Anarchist [tab] 103985 ... 324 [tab] 309 [tab] Melodies [tab] 230498 

什么是从File2中提取这些行的最简单的方法?

 $ while read p; do awk '$1 == "'$p'"' file2; done < file1 

要么:

 $ awk -F'\t' 'FNR==NR { a[$0]; next } $1 in a' file1 file2 
  • FNR :从正在处理的当前文件中读取的logging数
  • NR :inputlogging总数
  • FNR==NR :只有当awk正在读取file1时才为真
  • a[$0] :创build一个数组元素索引$0 (从file1
  • $1 in a :检查从file2中读取的每一行是否作为数组a中的一个索引存在

bash代码来做到这一点:

 for i in $(cat file1); do egrep "^$i\s" file2; done 

这可能是最快的:

 grep -f <( sed 's/.*/^&\t/' file1) file2 

使用forwhile循环的答案将会非常缓慢。

量子awk答案应该工作。 我不知道为什么它不会,除非你的行结束是非Unix或file1是非常大的。

1)我们可以使用一些grep的OR逻辑。 例如

 $> grep -P "^(324|399|408|135236|321590).*" file2 324 [tab] 309 [tab] Melodies [tab] 230498 

所以问题是 – 我们如何能得到这个variables的grep?

2)我们可以在单行中回显file1,用|替代分隔符 ,比添加括号。

 $> echo `cat file1` | sed -r -e 's/([0-9])\ ([0-9])/\1,\2/g' 324,399,408,135236,321590 

所以,最后我们有一个没有for-while循环的变体。

 grep -P "^($( echo `cat file1` | sed -r -e 's/([0-9])\ ([0-9])/\1|\2/g' )).*" file2 

join命令GNU coreutils服务器就是为了这个目的,但是对它的input却是挑剔的。

 $ sort file1 > sorted1 $ sort file2 > sorted2 $ join -t" " sorted1 sorted2 | sort -n 

join命令要求其input文件按字典顺序sorting,而不是数字sorting。 因此,input和输出的所有sorting。

要指定来自join的输出应该以制表符分隔,请使用-t" 制表符 " ,您可以在Bash提示符下键入Ctrl-V Tab