Усечь третий столбец до тех пор, пока не будут указаны строки

ВХОД:

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 – разделитель.

Это проще сделать с помощью awk вместо sed ; в случае awk – вариант:

 < input awk 'BEGIN {FS=OFS="\t"} {if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print}' 

Expanded:

 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} {if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print} : если третье поле записи ( $3 ) соответствует ( ~ ) регулярному выражению PT~ ( /PT~/ ) (т. е. если оно содержит его), замените первое левое самое широкое совпадение ( sub() ) регулярного выражение /.*PT~/ ( /.*PT~/ , которое соответствует всем до последнего появления подстроки PT~ ) с пустой строкой ( "" ) в третьем поле записи ( $3 ), в противном случае установите третье поле ( $3 ) в строку NA ( "NA" ), затем распечатайте запись;
 sed -e's/\(\t.*\t\).* PT~/\1/;t' \ -e's/\t[^\t]*/\tNA/2' 

Это должно сработать для вас, хотя оно остановит удаление дескрипторов при последнем появлении PT в последнем поле на линии.

Кроме того, в зависимости от вашей версии sed вам, возможно, придется использовать буквенные символы <tab> везде, где я использую escape \t .

Суть состоит в том, чтобы искать две вкладки на линии, разделенные любым количеством символов, и, если они находятся в какой-то точке, за которой следует строка <space>PT~ , то в s/// исключить все, кроме \1 го \( захваченная подгруппа \) в / address / pattern-space. Справедливости ради, это зависит от предела трех полей, но первый оператор замены может быть изменен следующим образом:

 sed -e's/^\(\([^\t]*\t\)\{2\}\)[^\t]* PT~/\1/;t' ... 

… портативно, или с помощью GNU или BSD …

 sed -Ee's/^(([^\t]*\t){2})[^\t]* PT~/\1/;t' ... 

… определенно ограничивать оператор s/// ubstitution только первыми тремя полями.

В любом случае, t est отпадает, если предыдущая подстановка успешна, и поэтому следующая s/// ubstitution заменяет поле с разделителями 3-ей закладки в строке, которая не соответствует строке <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