这可能是问题的延伸: Incorporate variables into bash code line
我刚才在文字中意识到,行实际上是变量格式的。
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
我需要的是
2 118610455 118610566
1 859214 860180
如上所示,此"END=#"
可能位于第8列的不同位置。所以基本上我需要先从第8列找到“END = ..”部分,然后grep这个数字。
所以这实际上是关于如何从字符串grep特定模式(在这种情况下,模式是“END =”)
但我怎么能这样做? THX
答案 0 :(得分:1)
您可以使用-o
的{{1}}选项进行搜索:
<强>测试强>
grep
但是如果你正在寻找一个完整的解决方案,那么如何使用[jaypal:~/Temp] grep -o "END=[0-9]\+;" file | tr -ds 'END=|;' ''
118610566
860180
(对不起,我知道这不是你的要求。但这里有两个解决方案:
如果您想要的第一个和第二个参数的位置不变,那么我们可以在特定字段中拆分每个值,然后遍历每个参数。只要我们到达awk
字段,我们就会打印$ 1和$ 4,然后打印END
旁边的列。
END
<强>测试强>
awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) if ($i=="END") print $1,$4,$(i+1)}' file
如果你有[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
,那么它有一个名为gawk
的内置函数。这支持反向引用。所以你也可以做以下事情 -
gensub
<强>测试强>
gawk '{print $1,$2,gensub(/.*\<END\>=(.[^;]*);.*/,"\\1",$0)}' file
答案 1 :(得分:0)
使用sed:
$ cat input | sed -e 's/^\([0-9]\+\) \+\([0-9]\+\) .*\<END=\([0-9]\+\).*/\1 \2 \3/'
答案 2 :(得分:0)
您可以使用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
一旦你理解它,它的工作方式很简单。 split
为您提供了一行元素,您只需稍微修改数字7即可。
如果它以END=
开头,那就去掉那个位。否则,如果一切都包括;END=
。
然后在第一个;
之后删除所有内容(在已经修改过的版本中,在开始时N
位为END=N
。)
然后打印出三个所需的值。
考虑到这一点,可能会更好一点,比如:
pax> 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,$x,$x,$c,$x)=split;$c=";$c";$c=~s/^.*;END=//;$c=~s/;.*$//;print "$a $b $c\n";}' <qq.in