截断第三列直到给定字符串

截断第三列直到给定字符串

输入:

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$3NA"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

相关内容