
Eu tenho um arquivo como este:
id target_id length eff_length
1 intron_FBgn0000721:20_FBgn0000721:18 1136 243.944268
1 intron_FBgn0000721:19_FBgn0000721:18 1122 240.237419
2 intron_FBgn0264373:2_FBgn0264373:3 56 0
3 intron_FBgn0027570:4_FBgn0027570:3 54 0
Para a 2ª coluna target_id
, quero manter apenas a string (nem sempre FBgnXXXX
, às vezes outros nomes) entre intron_
e a primeira :
. Portanto, o novo arquivo de saída terá o valor mais simples para a coluna 2, mas o restante do arquivo permanecerá o mesmo.
Tentei com o comando sed, mas não sei como deletar a parte que não preciso.
Responder1
Usando sed
e column
:
$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/' file | column -t
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
A parte principal disso é o comando substituto:
s/ intron_([^:]*):\S*/ \1/
Ele procura intron_
e salva tudo antes intron_
e depois dos primeiros dois pontos na variável 1
. [^[:space:]]*
corresponde a tudo, desde os dois pontos até o final do campo. Tudo isso é substituído pelo texto salvo na variável 1
.
Usando awk
com saída separada por tabulações:
$ awk -v "OFS=\t" '{$2=$2;sub(/intron_/, "", $2); sub(/:.*/, "", $2); print}' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
Explicação:
-v "OFS=\t"
Isso define o separador do campo de saída como uma guia. Isso ajuda a alinhar as colunas, possivelmente tornando
column
desnecessárias.$2=$2
Ao imprimir uma linha,
awk
não mudaremos para nosso separador de campo de saída recém-especificado, a menos que alteremos algo na linha. Atribuir o segundo campo ao segundo campo é suficiente para garantir que a saída terá tabulações.sub(/intron_/, "", $2)
Isso remove
intron_
do segundo campo.sub(/:.*/, "", $2)
Isso remove tudo após os primeiros dois pontos do segundo campo.
print
Isso imprime nossa nova linha.
Usando awk
com formatação de coluna personalizada
É semelhante ao anterior, mas é usado printf
para que possamos formatar larguras e alinhamentos de colunas conforme desejado:
$ awk '{sub(/intron_/, "", $2); sub(/:.*/, "", $2); printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4}' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
Aqui a instrução printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4
seleciona larguras e alinhamentos de colunas no printf
estilo usual.
Usando sed
e convertendo de separado por tabulação para separado por vírgula
$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/; s/[[:space:]][[:space:]]*/,/g' file
id,target_id,length,eff_length
1,FBgn0000721,1136,243.944268
1,FBgn0000721,1122,240.237419
2,FBgn0264373,56,0
Responder2
Você pode usar perl
:
$ perl -anle '
BEGIN {$" = "\t"}
print "@{[@F]}" and next if $. == 1;
$F[1] = $1 if /_([^:]*):/;
print "@{[@F]}";
' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
3 FBgn0027570 54 0
Explicação
-a
: divide automaticamente cada linha em array@F
.BEGIN {$" = "\t"}
: definimos o separador de lista como tab\t
, ele é usado quando um array ou fatia de array é interpolado em uma string entre aspas duplas.print "@{[@F]}" and next if $. == 1
: Imprimimos o cabeçalho e processamos para a próxima linha.$F[1] = $1 if /_([^:]*):/
: obtemos o valor entre_
e primeiro:
, salvamos no segundo elemento em@F
.print "@{[@F]}"
: basta imprimir o outpur desejado.
Responder3
sed -e 'h;s/.*intron_[^:]*\(:[^[:space:]]*\).*/\1/;s/./ /g;;G;;s/\(.*\)\n\(.*\)intron_\([^:]*\):[^[:space:]]*/\2\3\1/' YourFile
Em 1 sed (sem cano) mantendo a coluna. Ele usa o buffer de retenção
Versão Posix (assim --posix
em GNU sed)