3

我有一张这样的桌子:

symbol  refseq          seqname start           stop            strand
Susd4   NM_144796       chr1    184695027       184826500       +
Ptpn14  NM_008976       chr1    191552147       191700574       +
Cd34    NM_001111059    chr1    196765080       196787475       +
Gm5698  NM_001166637    chr1    31034088        31055753        -
Epha4   NM_007936       chr1    77363760        77511663        -
Sp110   NM_175397       chr1    87473474        87495392        -
Gbx2                    chr1    91824537        91827751        -
Kif1a                   chr1    94914855        94998430        -
Bcl2    NM_009741       chr1    108434770       108610879       -

我想提取具有以下条件的数据:

1)“refseq”列中的值不丢失的行

2)对于“ start”和“ stop”列中的值,每行只保留一个值:如果“ ”列中的值为strand+”,则取“ ”中的值start;如果“ ”列中的值为strand-”,则取“ ”中的值stop

这是预期的:

Susd4   NM_144796   chr1    184695027   +
Ptpn14  NM_008976   chr1    191552147       +
Cd34    NM_001111059    chr1    196765080       +
Gm5698  NM_001166637    chr1        31055753    -
Epha4   NM_007936   chr1        77511663    -
Sp110   NM_175397   chr1        87495392    -
Bcl2    NM_009741   chr1        108610879   -
4

4 回答 4

2

这可能对您有用(GNU sed):

sed -r '1d;/(\S+\s+){5}\S+/!d;/\+$/s/\S+\s+//5;/-$/s/\S+\s+//4' file

编辑:

  • 1d删除标题行
  • /(\S+\s+){5}\S+/!d;如果该行没有 6 个字段,请将其删除
  • /\+$/s/\S+\s+//5如果该行以+删除第 5 个字段结尾
  • /-$/s/\S+\s+//4如果该行以-删除第 4 个字段结尾
于 2013-01-12T16:53:53.090 回答
2

我很想不修改输入分隔符,以便空格和制表符分隔字段,而不是只坚持制表符。这意味着您希望在第一个(跳过标题行)之后有六个字段的记录:

awk 'NR > 1 && NF == 6 { if ($6 == "+") x = $4; else x = $5; print $1, $2, $3, x; }'

如果您想更多地控制输出格式,您可以使用 OFS 进行 dink,或者使用printf

awk 'BEGIN { OFS = "\t" }
     NR > 1 && NF == 6 { if ($6 == "+") x = $4; else x = $5; print $1, $2, $3, x; }'

awk 'NR > 1 && NF == 6 { if ($6 == "+") x = $4; else x = $5;
                         printf "%-8s %-12s %s %9s\n", $1, $2, $3, x; }'

还有其他方法可以处理它,我敢肯定...

第一个脚本产生:

Susd4 NM_144796 chr1 184695027
Ptpn14 NM_008976 chr1 191552147
Cd34 NM_001111059 chr1 196765080
Gm5698 NM_001166637 chr1 31055753
Epha4 NM_007936 chr1 77511663
Sp110 NM_175397 chr1 87495392
Bcl2 NM_009741 chr1 108610879

内容是正确的,我相信;可以通过多种方式改进格式。最后一个脚本产生:

Susd4    NM_144796    chr1 184695027
Ptpn14   NM_008976    chr1 191552147
Cd34     NM_001111059 chr1 196765080
Gm5698   NM_001166637 chr1  31055753
Epha4    NM_007936    chr1  77511663
Sp110    NM_175397    chr1  87495392
Bcl2     NM_009741    chr1 108610879

您可以根据需要调整字段宽度。

于 2013-01-11T21:00:27.523 回答
0

又快又脏,请检查它是否有效:

awk -F'\t' 'NR>1&&$2{print $NF=="+"?$4:$5}' file

输出:

184695027
191552147
196765080
31055753
77511663
87495392
108610879

如果您还想要输出中的其他值:

 awk 'BEGIN{FS=OFS="\t"}NR>1&&NF==6{print $1,$2,$3,$NF=="+"?$4:$5}' file 

输出:

Susd4   NM_144796       chr1    184695027
Ptpn14  NM_008976       chr1    191552147
Cd34    NM_001111059    chr1    196765080
Gm5698  NM_001166637    chr1    31055753
Epha4   NM_007936       chr1    77511663
Sp110   NM_175397       chr1    87495392
Bcl2    NM_009741       chr1    108610879

编辑,将格式调整为 OP 的输出示例:

awk 'BEGIN{FS=OFS="\t"}NR>1&&NF==6{$4=$NF=="+"?$4:" ";$5=$NF=="+"?" ":$5;print}' file

输出:

Susd4   NM_144796       chr1    184695027               +
Ptpn14  NM_008976       chr1    191552147               +
Cd34    NM_001111059    chr1    196765080               +
Gm5698  NM_001166637    chr1            31055753        -
Epha4   NM_007936       chr1            77511663        -
Sp110   NM_175397       chr1            87495392        -
Bcl2    NM_009741       chr1            108610879       -
于 2013-01-11T19:27:16.420 回答
0

当您处理带有字段的文本文件时,通常awk比旨在帮助解析带有字段的文本文件要好。sedawk

您的表格设置中的列如何?它们是制表符分隔的,还是您使用空格来帮助排列列?

如果这是一个制表符分隔的表,您可以awk用来检查第二个字段是否为空:

awk '
    {
        if ($2 == "") {
            print "Missing 'refseqence' in symbol " $1
        }
    ' $myfile

如果您的文件使用空格来对齐各个字段,您仍然可以awk通过使用其内置的 substr 函数来使用。

awk '
    {
        if (substr($0, 9, 12) ~ /^ *$/)
            print "Missing 'refsequence' in symbol " substr ($0, 1, 7)
        }
    }
' $myfile

顺便说一句,我在这里比较罗嗦,向您展示语法以使其易于理解。我本可以使用一些快捷方式将它们放在一行中:

awk '$2 == "" {print "Missing refseqence in symbol " $1}' $myfile
awk 'substr($0, 9, 12) ~ /^  */ {print "Missing refsequnece in symbol " substr($0, 1, 7) }' $myfile 
于 2013-01-11T20:10:22.123 回答