我想将同一行中的名称分成单独的对。
TMPRSS2|pp9284 AADAT Sample1
ERG TMPRSS2|pp9284 Sample2
TMPRSS2|pp9284 ETV1 Sample3
PDE4A MIA|MIA-RAB4B|RAB4B|RAB4B-EGLN2|EGLN2 Sample4
这应该是
TMPRSS2 AADAT Sample1
pp9284 AADAT Sample1
ERG TMPRSS2 Sample2
ERG pp9284 Sample2
TMPRSS2 ETV1 Sample3
pp9284 ETV1 Sample3
PDE4A MIA Sample4
PDE4A MIA-RAB4B Sample4
PDE4A RAB4B Sample4
PDE4A RAB4B-EGLN2 Sample4
PDE4A EGLN2 Sample4
多个名称都在两列中,所以我想要单独的对。我已经为此尝试过 mysql,因为在我有单独的对之后,我想将其与另一个表进行比较。 R 中的 strsplit 仅当多个名称的数量固定时才有效。但它们在每一行中都不同。我可以使用 sed、awk 来做到这一点吗?
还有某些列,其值保持相同,并且基本上同一行中的值保持相同。我应该如何打印这些列。我添加了第三列,其值被复制到新行中。为此,我使用了在 for 循环中打印 $3 也可以将它们打印出来,但不起作用。
答案1
$ awk '{split($1,a,"|"); split($2,b,"|"); for (i in a) {for (j in b) print a[i],b[j];}}' file
TMPRSS2 AADAT
pp9284 AADAT
ERG TMPRSS2
ERG pp9284
TMPRSS2 ETV1
pp9284 ETV1
PDE4A RAB4B-EGLN2
PDE4A EGLN2
PDE4A MIA
PDE4A MIA-RAB4B
PDE4A RAB4B
要同时打印第三个 ( SampleN
) 字段,您只需添加$3
到循环内的 print 语句即可,即
$ awk '{split($1,a,"|"); split($2,b,"|"); for (i in a) {for (j in b) print a[i],b[j],$3;}}' file
TMPRSS2 AADAT Sample1
pp9284 AADAT Sample1
ERG TMPRSS2 Sample2
ERG pp9284 Sample2
TMPRSS2 ETV1 Sample3
pp9284 ETV1 Sample3
PDE4A RAB4B-EGLN2 Sample4
PDE4A EGLN2 Sample4
PDE4A MIA Sample4
PDE4A MIA-RAB4B Sample4
PDE4A RAB4B Sample4
答案2
使用bash:
# important to use parentheses, not braces, to localize changes to IFS
# the variable is purposefully unquoted
split_pipe() ( IFS='|'; echo $1 )
while read -r first second third; do
for word1 in $(split_pipe "$first"); do
for word2 in $(split_pipe "$second"); do
echo $word1 $word2 $third
done
done
done < file
答案3
使用 GNU,sed
您可以执行以下操作:
sed -E 's/(\|[^ |]+) /\1| /
s/(([^|]* )?([^|]*))\|(([^ ]*)(.*))/\1\6\n\2\4/
/\n/P;D' <infile
...打印...
TMPRSS2 AADAT Sample1
pp9284 AADAT Sample1
ERG TMPRSS2 Sample2
ERG pp9284 Sample2
TMPRSS2 ETV1 Sample3
pp9284 ETV1 Sample3
PDE4A MIA Sample4
PDE4A MIA-RAB4B Sample4
PDE4A RAB4B Sample4
PDE4A RAB4B-EGLN2 Sample4
PDE4A EGLN2 Sample4
它的工作原理是分割并打印,然后逐个删除多余的\n
行字符上的一行内容。该P
命令P
仅打印\n
模式空间中第一个出现的 ewline,因此您可以根据需要轻松地仅打印编辑缓冲区的一部分。
在这种情况下,对于每个不包含空格的管道划分部分,sed
将所有位两次放置在编辑缓冲区的任一端。sed
将最左端和最右端插入到最左侧管道划分部分的左侧和右侧,并按照该顺序使用 ewline \n
,然后将相同的选择放在保留在右侧的所有管道划分部分的任一端-其插入的线的手侧\n
。因此,如果模式空间中根本存在 ewline,则sed
可以P
仅打印左侧的位,然后仅删除模式空间中第一个出现的 ewline 并重试。\n
D
\n
第一次替换只发生一次 - 它只是将一个管道附加到管道分隔部分的末尾,因此总是有一个管道可以分隔 - 即使是最后一次出现。其余时间,sed
进行一次s///
替换,P
在模式空间中打印第一行,然后D
进行相同的删除。当它不能再这样做时,它D
就会删除全部模式空间并自动拉入下一个输入行。
可以编写用于执行相同操作的 POSIX BRE:
sed ' s/\(|[^ |]\{1,\}\) /\1| /
s/^\(\( *[^ |]* *\)*\([^ |]*\)\)|\(\([^ ]*\)\(.*\)\)/\1\6\
\2\4/; /\n/P;D' <infile