输入:
W41784094 CH60104475 lasbalsrbla bla foo bar bla PT~CH60104475
W41788464 WO60444453 hellobla bla -bla foo bar 432 alaf. PT~CH60107925
W41753387 IN61026681 sim##bla-bla bla foo bar blab lba la:bla32 bla
输出:
W41784094 CH60104455 CH60104455
W41788464 WO60444453 CH60107925
W41753387 IN61026681 NA
问题:如何截断第三列直到“ PT~”?
但如果不总是有“PT~”,则需要“NA”:\
Tab 是分隔符。
答案1
awk
使用代替;更容易完成此操作sed
。如果awk
是一个选项:
< input awk 'BEGIN {FS=OFS="\t"} {if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print}'
扩展:
BEGIN {
FS=OFS="\t"
}
{
if ($3 ~ /PT~/)
sub(/.*PT~/, "", $3);
else
$3 = "NA";
print
}
BEGIN {FS=OFS="\t"}
:将字段分隔符1和输出字段分隔符2设置为TAB
,以便每个TAB
- 分隔的字符串都作为记录的字段 ( 1 ),并在每个记录之后打印分隔符 ( 2 );{if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print}
:如果记录的第三个字段 ( ) 与 ( ) 正则表达式( )$3
匹配(即如果包含它),则替换正则表达式 ( ) 的第一个最左边的最宽匹配 ( ) ,这会匹配所有内容,直到最后一次出现子字符串)在记录 ( ) 的第三个字段 ( ) 中添加一个空字符串 ( ) ,否则将第三个字段 ( ) 设置为字符串 ( ),然后打印该记录;~
PT~
/PT~/
sub()
/.*PT~/
/.*PT~/
PT~
""
$3
$3
NA
"NA"
答案2
sed -e's/\(\t.*\t\).* PT~/\1/;t' \
-e's/\t[^\t]*/\tNA/2'
这应该对你有用,尽管它只会停止在最后的的发生PT
在该行的最后一个字段中。
此外,根据你的sed
版本,你可能必须在我使用\t
逃脱。
要点是在一行上查找由任意数量的字符分隔的两个制表符,并且如果它们在某个点后跟字符串<space>PT~
,然后替换除所寻址模式空间的st捕获子组s///
之外的所有子组。公平地说,这依赖于三个字段的限制,但第一个替换语句可能会更改为:\1
\(
\)
/
/
sed -e's/^\(\([^\t]*\t\)\{2\}\)[^\t]* PT~/\1/;t' ...
...可移植,或者使用 GNU 或 BSD sed
...
sed -Ee's/^(([^\t]*\t){2})[^\t]* PT~/\1/;t' ...
...将替换语句明确限制s///
为仅前 3 个字段。
在任何情况下,t
如果前一个替换成功,则 est 分支离开,因此下一个s///
替换将替换与不匹配的行上的第三个制表符分隔字段。<space>PT~
仅包含字符串的字符串NA
。
sed -e's/\(\t.*\t\).* PT~/\1/;t' \
-e's/\t[^\t]*/\tNA/2' <<\IN
W41784094 CH60104475 lasbalsrbla bla foo bar bla PT~CH60104475
W41788464 WO60444453 hellobla bla -bla foo bar 432 alaf. PT~CH60107925
W41753387 IN61026681 sim##bla-bla bla foo bar blab lba la:bla32 bla
IN
W41784094 CH60104475 CH60104475
W41788464 WO60444453 CH60107925
W41753387 IN61026681 NA