我需要从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
使用for和while循环的答案将会非常缓慢。
量子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 。