使用awk,sed或R基于字符串模式复杂提取所有行条目

时间:2019-07-10 12:25:57

标签: r awk sed grep data-munging

我有一个7列的文件,如下所示:

ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)|
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)|
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|

我正在尝试使用grep,sed,awk或R查找解决方案。我需要从空格分隔的文本文件中提取所有第6列(INFO_TAGS_USED_TO_ANNOTATE column)中值1出现在之后的实例中的所有内容。逗号。

每当出现1时,以行1为例,我需要为每个实例保留的信息为1:154834911(1.2e-05,1)。此信息对应于SNP信息,即chromosome number:base position(p-value,annotation=1)

如果特定行中出现多个1的实例,那么我需要每个实例,并报告相应的SNP信息。因此,以第2行为例,将报告两个实例3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)

如果可能的话,每行提取的信息将附加到新列中。

第6列中的每个条目都由|分隔。如果为特定行报告了多个条目,则在新列中使用|作为定界符将很有用。

上面输出的最后一列的输出看起来像这样

NewCol
1 1:154834911(1.2e-05,1)
2 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)
3 <empty>

请注意,第5、6和7列中的信息非常相似,可能会造成混淆。

任何建议将不胜感激。

4 个答案:

答案 0 :(得分:1)

perl在这里可以很好地工作:

perl -lane '
    if ($. == 1) {
        $val = "NewCol";
    } else {
        $val = join "|", grep {/,1\)/} split /\|/, $F[5];
    }
    print join " ", @F, $val;
' file
ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE NewCol
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)| 1:154834911(1.2e-05,1)
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)| 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|

这是魔术:$val = join "|", grep {/,1\)/} split /\|/, $F[5]; -您必须从右到左阅读该内容:

  • 首先使用管道(这是一个特殊的正则表达式字符)分割第6个字段(perl使用基于0的索引),
  • 然后仅在逗号后和右括号前保留带有“ 1”的位,
  • 然后将其余的位与管道连接起来。

如果您想惹恼您的同事,可以将其打倒

perl -lape '$_=join" ",@F,$.==1?"NewCol":join"|",grep{/,1\)/}split/[|]/,$F[5]' file

答案 1 :(得分:1)

使用R读入myfile,如注释行中所示,然后使用gsub删除不需要的部分,将剩下的部分放入新列中。使用的数据显示在末尾。

library(gsubfn)
# DF <- read.table("myfile", header = TRUE, as.is = TRUE, 
#   check.names = FALSE, strip.white = TRUE)
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE, 
  check.names = FALSE, strip.white = TRUE)

transform(DF, NEWCOL = gsub("([^,]+),[^1]\\)\\|", "", INFO_TAGS_USED_TO_ANNOTATE))

注意

Lines <- "
ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)|
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)|
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|
"

答案 2 :(得分:1)

在每个UNIX框的任何外壳中使用任何awk:

<r><Postcode>ACB</Postcode></r>

答案 3 :(得分:1)

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

sed -E 'h;s/\S+/\n&\n/6;s/.*\n(.*)\n.*/\1/;s/[^,]+,([^1)]|[^)]{2,})\|//g;s/\|$//;1s/.*/newcol/;H;g;s/\n/ /' file

复制该行,隔离第6个字段,删除逗号后不包含1的字符串,删除最后一个|并将结果附加到原始行。