从混乱的文件中提取名称

时间:2014-09-05 14:37:49

标签: 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|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'之后会提取包含此名称信息的列。

请帮助。

谢谢。

5 个答案:

答案 0 :(得分:6)

使用标准剪切命令

提取字段

使用管道符号作为字段分隔符,并使用标准 cut 命令提取第5个字段。例如:

$ cut -d\| -f5 /tmp/corpus
SAMD11
SAMD11
SAMD11
SAMD11
SAMD11
NOC2L
NOC2L
NOC2L
KLHL17
NOC2L

答案 1 :(得分:5)

你可以使用awk,

$ awk -F\| '{print $5}' file
SAMD11
SAMD11
SAMD11
SAMD11
NOC2L
NOC2L
NOC2L
KLHL17
NOC2L

如果要删除重复项,请将awk输出传递给sort -u

$ awk -F\| '{print $5}' file | sort -u
KLHL17
NOC2L
SAMD11

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

awk -F\| '!seen[$5]++ && $0=$5' file

答案 2 :(得分:5)

Avinash Raj's awk solution一样,这可以在Perl中完成,方式完全相同。您还可以包含相同的重复数据删除流程:

perl -F'\|' -lane'print $F[4] if !$seen{$F[4]}++;' yourfile.txt
  • 对于!$seen{$F[4]}++哈希中的任何新密钥,%seen语句返回true。
  • -a开关是autosplit,-F设置分隔符(以正则表达式的形式)。
  • -l处理print
  • 的换行符
  • -n将程序代码放在while (<>)循环中,该循环将读取文件或标准输入。

答案 3 :(得分:2)

Pure bash

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[@]}"

打印

NOC2L
KLHL17
SAMD11

while IFS='|' read -r a b c d e f g
do
        echo "$e"
done <$file | something

答案 4 :(得分:2)

Pure Bash One-Liner

如果您不想使用 cut awk ,您可以使用Bash read builtin进行同样的思考。基本上,这会将输入字段分隔符设置为管道符号,将每行读取到名为 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