我遇到grep和awk的问题。我认为这是因为我的输入文件包含看起来像代码的文本。
输入文件包含ID名称,如下所示:
SNORD115-40
MIR432
RNU6-2
参考文件如下所示:
Ensembl Gene ID HGNC symbol
ENSG00000199537 SNORD115-40
ENSG00000207793 MIR432
ENSG00000266661
ENSG00000243133
ENSG00000207447 RNU6-2
我想将源文件中的ID名称与我的参考文件相匹配,并打印出相应的ensg ID号,以便输出文件如下所示:
ENSG00000199537 SNORD115-40
ENSG00000207793 MIR432
ENSG00000207447 RNU6-2
我试过这个循环:
exec < source.file
while read line
do
grep -w $line reference.file > outputfile
done
我也尝试使用awk
来使用参考文件awk 'NF == 2 {print $0}' reference file
awk 'NF >2 {print $0}' reference file
但我只获得了一个grep'dID。
任何建议或更简单的方法都会很棒。
答案 0 :(得分:8)
$ fgrep -f source.file reference.file
ENSG00000199537 SNORD115-40
ENSG00000207793 MIR432
ENSG00000207447 RNU6-2
fgrep
相当于grep -F
:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
-f
选项用于从文件中获取PATTERN
:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
如评论中所述,如果reference.file
中的ID包含source.file
中的ID作为子字符串,则会产生误报。您可以使用grep
动态构建sed
更明确的模式:
grep -f <( sed 's/.*/ &$/' input.file) reference.file
但是这样,模式被解释为正则表达式而不是固定字符串,这可能是易受攻击的(尽管如果ID只包含字母数字字符,则可能没问题)。但是,更好的方法(感谢@sidharthcnadhan)是使用-w
选项:
-w, --word-regexp
Select only those lines containing matches that form whole
words. The test is that the matching substring must either be
at the beginning of the line, or preceded by a non-word
constituent character. Similarly, it must be either at the end
of the line or followed by a non-word constituent character.
Word-constituent characters are letters, digits, and the
underscore.
所以你问题的最终答案是:
grep -Fwf source.file reference.file
答案 1 :(得分:4)
这样可以解决问题:
$ awk 'NR==FNR{a[$0];next}$NF in a{print}' input reference
ENSG00000199537 SNORD115-40
ENSG00000207793 MIR432
ENSG00000207447 RNU6-2
答案 2 :(得分:1)
这是一个不错的bash
尝试。问题是您始终覆盖结果文件。使用'&gt;&gt;'代替>
或在>
done
grep -w $line reference.file >> outputfile
或
done > outputfile
但我更喜欢Lev的解决方案,因为它只启动一次外部过程。
如果你想在纯bash
中解决它,你可以试试这个:
ID=($(<IDfile))
while read; do
for((i=0;i<${#ID[*]};++i)) {
[[ $REPLY =~ [[:space:]]${ID[$i]}$ ]] && echo $REPLY && break
}
done <RefFile >outputfile
cat outputfile
输出:
ENSG00000199537 SNORD115-40
ENSG00000207793 MIR432
ENSG00000207447 RNU6-2
较新的bash
支持关联数组。它可用于简化和加速搜索密钥:
declare -A ID
for i in $(<IDfile); { ID[$i]=1;}
while read v; do
[[ $v =~ [[:space:]]([^[:space:]]+)$ && ${ID[${BASH_REMATCH[1]}]} = 1 ]] && echo $v
done <RefFile