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