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



>我有一个像这样的 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 列中的信息非常相似,可能会造成混淆。

任何建议将不胜感激。

使用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)|
"

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

在每个 UNIX 机器上使用任何 shell 中的任何 awk:

$ cat tst.awk
NR==1 { print $0, "NewCol"; next }
{
new = sep = ""
n = split($6,f,/[|]/)
for (i=1; i<=n; i++) {
if ( f[i] ~ /,1/ ) {
new = new sep f[i]
sep = "|"
}
}
print $0, new
}
$ awk -f tst.awk 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)|

这可能对你有用(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的字符串,删除最后的|并将结果附加到原始行。

最新更新