Perl 从混乱的文件中提取名称

Perl 从混乱的文件中提取名称,perl,awk,grep,Perl,Awk,Grep,我有一个如下所示的文本文件: MODIFIER|||c.72+1731G>T|SAMD11|protein_coding|CODING|NM_152486.2|2) MODIFIER|||c.73-597G>A|SAMD11|protein_coding|CODING|NM_152486.2|2) MODIFIER|||c.306-249T>C|SAMD11|protein_coding|CODING|NM_152486.2|4) MODIFIER||2842||SAMD11|

我有一个如下所示的文本文件:

MODIFIER|||c.72+1731G>T|SAMD11|protein_coding|CODING|NM_152486.2|2)
MODIFIER|||c.73-597G>A|SAMD11|protein_coding|CODING|NM_152486.2|2)
MODIFIER|||c.306-249T>C|SAMD11|protein_coding|CODING|NM_152486.2|4)
MODIFIER||2842||SAMD11|protein_coding|CODING|NM_152486.2|)
MODIFIER||4854||SAMD11|protein_coding|CODING|NM_152486.2|)
MODIFIER|||c.1443+808T>C|NOC2L|protein_coding|CODING|NM_015658.3|12)
LOW|||c.889C>G|NOC2L|protein_coding|CODING|NM_015658.3|8)
LOW|||c.889T>G|NOC2L|protein_coding|CODING|NM_015658.3|8)
MODIFIER||2687||KLHL17|protein_coding|CODING|NM_198317.2|)
MODIFIER||2885||NOC2L|protein_coding|CODING|NM_015658.3|)
我想提取SAMD11、NOC2L和KLHL17等名称

如果这些文件以精确的模式出现,我会使用tr作为

tr'|''\t'和之后将提取包含此名称信息的列

请帮忙

谢谢。

您可以使用awk

$ awk -F\| '{print $5}' file
SAMD11
SAMD11
SAMD11
SAMD11
NOC2L
NOC2L
NOC2L
KLHL17
NOC2L
如果要删除重复项,请将awk输出传递给sort-u

正如@jaypal所建议的,您可以使用下面的awk one-liner命令删除重复项

awk -F\| '!seen[$5]++ && $0=$5' file
使用标准剪切命令提取字段 使用管道符号作为字段分隔符,并使用标准剪切命令提取第5个字段。例如:

$ cut -d\| -f5 /tmp/corpus
SAMD11
SAMD11
SAMD11
SAMD11
SAMD11
NOC2L
NOC2L
NOC2L
KLHL17
NOC2L
就像,这可以在Perl中完成,完全相同。您还可以包括相同的重复数据消除过程:

perl -F'\|' -lane'print $F[4] if !$seen{$F[4]}++;' yourfile.txt
这个$SEED{$F[4]}++语句为%SEED哈希中的任何新键返回true。 -a开关是autosplit,其中-F以正则表达式的形式设置分隔符。 -l处理打印的换行符,以及 -n将程序代码放入while循环中,该循环将读取文件或标准输入。 纯粹的狂欢

declare -A seen
while IFS='|' read -r a b c d e f g
do
        let seen[$e]++
done <<'EOF'
MODIFIER|||c.72+1731G>T|SAMD11|protein_coding|CODING|NM_152486.2|2)
MODIFIER|||c.73-597G>A|SAMD11|protein_coding|CODING|NM_152486.2|2)
MODIFIER|||c.306-249T>C|SAMD11|protein_coding|CODING|NM_152486.2|4)
MODIFIER||2842||SAMD11|protein_coding|CODING|NM_152486.2|)
MODIFIER||4854||SAMD11|protein_coding|CODING|NM_152486.2|)
MODIFIER|||c.1443+808T>C|NOC2L|protein_coding|CODING|NM_015658.3|12)
LOW|||c.889C>G|NOC2L|protein_coding|CODING|NM_015658.3|8)
LOW|||c.889T>G|NOC2L|protein_coding|CODING|NM_015658.3|8)
MODIFIER||2687||KLHL17|protein_coding|CODING|NM_198317.2|)
MODIFIER||2885||NOC2L|protein_coding|CODING|NM_015658.3|)
EOF

printf "%s\n" "${!seen[@]}"

一次纯粹的狂欢 如果您不想使用cut或awk,您可以对Bash的进行同样的思考。基本上,这将输入字段分隔符设置为管道符号,将每一行读入一个名为line的数组;然后打印第5个字段,因为数组索引从0开始

$ while IFS='|' read -a line; do echo "${line[4]}"; done < /tmp/foo
SAMD11
SAMD11
SAMD11
SAMD11
SAMD11
NOC2L
NOC2L
NOC2L
KLHL17
NOC2L

嗨,阿维纳什,你能给我推荐一本书吗。在那里我可以很好地掌握bash中的所有技巧。@AvinashRaj对于单个命令,您可以执行awk-F \|'!已查看[$5]+&&$0=$5'文件经典:。Awk是一种完整的编程语言,采用文件读取循环。它可以取代grep、cut、tail、head等。我不需要那本sed和awk的书,因为你不需要一本书来学习sed应该在一行上用于简单的替代,而awk最好是从Arnold Robbins编写的更有效的awk编程第三版中学习。要了解bash,请尝试Chris Johnson的bash脚本编写方法。我以为您将要执行perl-F'\\\'-lane'$seen{$F[4]}++或打印$F[4]'文件:不,这是我要做的$s{$\}++或$F[4]@jaypal打印,除非看到$s。。也许会更直观,但我认为使用惯用语是好的$看到{..}++image。大体上同意,但不一定是一行程序。仅供参考,您的文件一点也不混乱;它只是用管道分隔的,有些字段是空的。Wrt我会那是错误的方法很好,仅供参考。。关联数组需要BashV4。@jaypal-yay,没错。。。OS X上的第一件事是安装macports和新的bash…没错,我没有使用macports。。改为使用自制啤酒:
NOC2L
KLHL17
SAMD11
while IFS='|' read -r a b c d e f g
do
        echo "$e"
done <$file | something
$ while IFS='|' read -a line; do echo "${line[4]}"; done < /tmp/foo
SAMD11
SAMD11
SAMD11
SAMD11
SAMD11
NOC2L
NOC2L
NOC2L
KLHL17
NOC2L