String 使用bash从字符串中获取特定模式

String 使用bash从字符串中获取特定模式,string,grep,design-patterns,String,Grep,Design Patterns,这可能是问题的延伸: 我刚刚意识到,在我的文本中,行实际上是可变格式的 2 118610455 P2_PM_2_5034 T <DUP:TANDEM> 40 . END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP 1 859214 P2_M_06

这可能是问题的延伸:

我刚刚意识到,在我的文本中,行实际上是可变格式的

2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP 

1   859214  P2_M_061510_1_73    C   <DEL>   .   .   CIEND=-130,50;CIPOS=-57,93;END=860180;IMPRECISE;SVLEN=-966;SVTYPE=DEL;VALIDATED;DBVARID=esv10036;VALMETHOD=CGH;SVMETHOD=RD,RP
正如上面所示,此
“END=#”
可能位于第8列的不同位置。所以基本上我需要先从第8列中找到“END=…”部分,然后grep数字。 这实际上是关于如何从字符串中grep特定的模式(在本例中,模式是“END=”)

但是我怎么能做到呢? thx使用sed:

$ cat input | sed -e 's/^\([0-9]\+\) \+\([0-9]\+\) .*\<END=\([0-9]\+\).*/\1 \2 \3/'

$cat input | sed-e的/^\([0-9]\+\)\+\([0-9]\+\).\您可以使用perl脚本来实现这一点,例如:

pax> perl -ne '{
         @arr=split;
         if (@arr[7] =~ /^END=/) {
             @arr[7] =~ s/^END=//;
         } else {
             @arr[7] =~ s/^.*;END=//;
         }
         @arr[7] =~ s/;.*$//;
         printf "%s %s %s\n", @arr[0], @arr[1], @arr[7];
     }' <qq.in
2 118610455 118610566
1 859214 860180
或同等的一个班轮:

perl -ne '{@arr=split;if (@arr[7] =~ /^END=/) {@arr[7] =~ s/^END=//;} else {@arr[7] =~ s/^.*;END=//;} @arr[7] =~ s/;.*$//; printf "%s %s %s\n", @arr[0], @arr[1], @arr[7];}' <qq.in
perl -ne '{($a,$b,$x,$x,$x,$x,$x,$c,$x)=split;$c=";$c";$c=~s/^.*;END=//;$c=~s/;.*$//;print "$a $b $c\n";}' <qq.in
perl-ne'{($a,$b,$x,$x,$x,$c,$x)=拆分;$c=“;$c”;$c=~s/^.*;END=/;$c=~s/;*$/;打印“$a$b$c\n”;”}Grep:
您可以使用
grep
-o
选项进行搜索:

测试:

[jaypal:~/Temp] grep -o "END=[0-9]\+;" file | tr -ds 'END=|;' ''
118610566
860180
[jaypal:~/Temp] cat file
2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP 
1   859214  P2_M_061510_1_73    C   <DEL>   .   .   CIEND=-130,50;CIPOS=-57,93;END=860180;IMPRECISE;SVLEN=-966;SVTYPE=DEL;VALIDATED;DBVARID=esv10036;VALMETHOD=CGH;SVMETHOD=RD,RP

[jaypal:~/Temp] awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) if ($i=="END") print $1,$4,$(i+1)}' file
2 118610455 118610566
1 859214 860180
[jaypal:~/Temp] gawk '{print $1,$2,gensub(/.*\<END\>=(.[^;]*);.*/,"\\1",$0)}' file
2 118610455 118610566
1 859214 860180

但是如果您正在寻找一个完整的解决方案,那么使用
awk
(很抱歉,我知道这不是您的要求。但这里有两个解决方案:

Awk: 如果您想要的第一个和第二个参数在位置上没有变化,那么我们可以在特定字段中拆分每个值,然后在每个值上循环。一旦到达
END
字段,我们将打印$1和$4,然后打印
END
旁边的列

awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) if ($i=="END") print $1,$4,$(i+1)}' file
测试:

[jaypal:~/Temp] grep -o "END=[0-9]\+;" file | tr -ds 'END=|;' ''
118610566
860180
[jaypal:~/Temp] cat file
2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP 
1   859214  P2_M_061510_1_73    C   <DEL>   .   .   CIEND=-130,50;CIPOS=-57,93;END=860180;IMPRECISE;SVLEN=-966;SVTYPE=DEL;VALIDATED;DBVARID=esv10036;VALMETHOD=CGH;SVMETHOD=RD,RP

[jaypal:~/Temp] awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) if ($i=="END") print $1,$4,$(i+1)}' file
2 118610455 118610566
1 859214 860180
[jaypal:~/Temp] gawk '{print $1,$2,gensub(/.*\<END\>=(.[^;]*);.*/,"\\1",$0)}' file
2 118610455 118610566
1 859214 860180
[jaypal:~/Temp]gawk'{print$1,$2,gensub(/.*\=([^;]*);.*/,“\\1,$0)}文件
2 118610455 118610566
1 859214 860180