2014-01-12 53 views
1

我想转换,例如字符串:有多个匹配和条件sed的正则表达式

abc=123.24|127.9|2891;xyz;hgy 

到:

abc=123.24,127.9,2891;xyz;hgy 

这是接近:

echo "abc=123.24|127.9|2891;xyz;hgy" | sed -r 's/(=)([0-9.]+)\|/\1\2,/g' 

但回报:

abc=123.24,127.9|2891;xyz;hgy 

如果条形分隔的数字的数量是可变的,我怎样才能以类似的方式做其余的数字?

澄清

我讨厌别人不给我问题的全貌,但我上面的原始描述就是这样做的。这个小例子嵌入在一个更大的行中,包括“|”分隔文本。我只想替换“|”与“,”之间的数字之间等号。这里是整条生产线为例:

chr1 69511 rs75062661 A G . QSS_ref ASP;BaseCounts=375,3,118,4;CAF=[0.348,0.652];COMMON=1;EFF=NON_SYNONYMOUS_CODING(MODERATE|MISSENSE|Aca/Gca|T141A|305|OR4F5|protein_coding|CODING|ENST00000335137|1|1);GNO;HRun=0;HaplotypeScore=0.0000;KGPROD;KGPhase1;LowMQ=0.0280,0.0580,500;MQ=49.32;MQ0=14;MSigDb=ACEVEDO_METHYLATED_IN_LIVER_CANCER_DN,KEGG_OLFACTORY_TRANSDUCTION,REACTOME_GPCR_DOWNSTREAM_SIGNALING,REACTOME_OLFACTORY_SIGNALING_PATHWAY,REACTOME_SIGNALING_BY_GPCR,chr1p36;NORMALT=86;NORMREF=228;NSM;NT=het;OTHERKG;QSS=8;QSS_NT=6;REF;RS=75062661;RSPOS=69511;S3D;SAO=0;SGT=AG->AG;SOMATIC;SSR=0;TQSS=1;TQSS_NT=2;TUMALT=15;TUMREF=227;TUMVAF=0.06198347107438017;TUMVARFRACTION=0.1485148514851485;VC=SNV;VLD;VP=0x050200000a05140116000100;WGT=1;dbNSFP_1000Gp1_AC=1424;dbNSFP_1000Gp1_AF=0.652014652014652;dbNSFP_1000Gp1_AFR_AC=162;dbNSFP_1000Gp1_AFR_AF=0.32926829268292684;dbNSFP_1000Gp1_AMR_AC=235;dbNSFP_1000Gp1_AMR_AF=0.649171270718232;dbNSFP_1000Gp1_ASN_AC=500;dbNSFP_1000Gp1_ASN_AF=0.8741258741258742;dbNSFP_1000Gp1_EUR_AC=527;dbNSFP_1000Gp1_EUR_AF=0.6952506596306068;dbNSFP_29way_logOdds=4.1978;dbNSFP_29way_pi=0.1516:0.0:0.6258:0.2226;dbNSFP_ESP6500_AA_AF=0.544101;dbNSFP_ESP6500_EA_AF=0.887429;dbNSFP_Ensembl_geneid=ENSG00000186092;dbNSFP_Ensembl_transcriptid=ENST00000534990|ENST00000335137;dbNSFP_FATHMM_score=0.51;dbNSFP_GERP++_NR=2.31;dbNSFP_GERP++_RS=1.15;dbNSFP_Interpro_domain=GPCR|_rhodopsin-like_superfamily_(1)|;dbNSFP_LRT_Omega=0.000000;dbNSFP_LRT_pred=N;dbNSFP_LRT_score=0.000427;dbNSFP_MutationAssessor_pred=neutral;dbNSFP_MutationAssessor_score=-1.295;dbNSFP_MutationTaster_pred=N;dbNSFP_MutationTaster_score=0.000162;dbNSFP_Polyphen2_HDIV_pred=B;dbNSFP_Polyphen2_HVAR_pred=B;dbNSFP_SIFT_score=0.950000;dbNSFP_Uniprot_aapos=141;dbNSFP_Uniprot_acc=Q8NH21;dbNSFP_Uniprot_id=OR4F5_HUMAN;dbNSFP_aaalt=A;dbNSFP_aapos=189|141;dbNSFP_aaref=T;dbNSFP_cds_strand=+;dbNSFP_codonpos=1;dbNSFP_fold-degenerate=0;dbNSFP_phyloP=0.267000;dbNSFP_refcodon=ACA;dbSNPBuildID=131 AU:CU:DP:FDP:GU:SDP:SUBDP:TU 228,232:3,3:322:4:86,109:0:0:1,2 227,228:0,0:244:1:15,16:0:0:1,2 

在这一行替换为字符串:

dbNSFP_aapos=189|141 

有:

dbNSFP_aapos=189,141 
+0

你用'sed'卡住了吗? – Birei

+0

没有。但是,我试图通过管道“内联”来避免跟踪工作流中的其他脚本。 – seandavi

回答

1

作为替代方案,您可以用尝试及其evalutation标志:

echo "..." | perl -pe 's{=([\d.|]+)}{"=" . (join ",", split /\|/, $1)}eg' 

它在等号后搜索字符串,将其与|分开并用逗号加入。

2

为什么不:

sed 's/|/,/g' 


kent$ echo "abc=123.24|127.9|2891;xyz;hgy"|sed 's/|/,/g' 
abc=123.24,127.9,2891;xyz;hgy 
+0

为什么不呢?因为在正则表达式中,人们往往认为过于复杂:) +1,因为你比我快了几秒 –

+0

甚至'tr'|' ',' – tripleee

+1

或者因为OP没有给你完整的问题 - 对不起。请参阅上面的说明。 – seandavi

0

假设分号是你的字段分隔符,如何abou有点像

tr `;\n' '\n;' | sed '/=[0-9.|]*$/s/|/,/g' | tr '\n;' ';\n' 

这有一个严重的缺陷;它在一行上的第一个和最后一个字段以奇怪的方式失败。如果你不能忍受这一点,也许试试这个:

awk -F ';' '{ for(i=1; i<=NF; ++i) if ($i ~ /=([0-9.]+\|)+[0-9.]+$/) gsub(/\|/,",",$i); print }' 
+0

您在比较条件中错过了结尾“/”。 '($ i〜/=([0-9.]+\|)+[0-9.]+$/)' – BMW

+0

@宝马谢谢;编辑。 – tripleee

0

使用tr

echo "abc=123.24|127.9|2891;xyz;hgy" | tr \| , 
abc=123.24,127.9,2891;xyz;hgy 
2

没有用perl可以使用

input="abc=123;def=hello123test;dbNSFP_aapos=189|141|142;dbNSFP_aaref=T;another=test|hello;" 

sed -r 's/(.*=)([0-9.]+\|)+(.*)/\1'$(sed -r 's/(.*=)([0-9.]+\|)+(.*)/\2/' <<< $input | tr '|' ,)'\3/' <<< $input 

输出:

abc=123;def=hello123test;dbNSFP_aapos=189,141,142;dbNSFP_aaref=T;another=test|hello; 

替换<<< $input与您的文件或任何你确实有输入:)

说明:

我们在正则表达式中有三个捕获组(我重组了gro第二个将只包含替换|的字符串,而第一个和第三个包含第二个组之前和之后的所有内容。
请参阅demo @ regex101

在第二个命令($(...))内,我们用sed抓住第二个捕获组,并用逗号替换每个|。这个替换然后被用于在另一个sed-调用中的第二组的地方。