Abordagem curta sed :
sed 's/^\(.*\t\)[^;]*;//' file
A saída:
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
-
\(.*\t\)
- capturando a parte necessária da primeira seção
Eu tenho um arquivo com muitas linhas. Cada linha começa com um padrão gi_[0-9]
, logo após, há uma tabulação e, depois disso, uma lista de palavras, todas separadas por ponto e vírgula. Eu gostaria que apenas as 8 últimas palavras permanecessem (7 seções, porque a última seção tem 2 palavras).
Veja um exemplo de arquivo de entrada :
gi_1\tDog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2\tPork;Black;White;Beige;Brown;Cyan;Purple;Red pepper
O resultado correspondente deve ser:
gi_1\tPink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2\tBlack;White;Beige;Brown;Cyan;Purple;Red pepper
Nota : não encontrei o caminho para inserir uma guia, por isso escrevi \ t em vez disso, mas há marcas de tabulação no meu arquivo.
com awk
:
awk -F '\t' -v OFS='\t' 'sub("^[^;]*;", "", $2)' file.txt
sub("^[^;]*;", "", $2)
substitui a subcadeia até primeiro ;
do início da guia separado ( -F '\t'
) segundo campo com nulo. sub()
faz a substituição no local
-v OFS='\t'
define o separador do campo de saída como guia
O primeiro campo (e todo o resto) é mantido como está
Para fins de integridade, verifique se o primeiro campo é gi_
seguido por um dígito:
awk -F '\t' -v OFS='\t' '$1 ~ /^gi_[[:digit:]]$/ {sub("^[^;]*;", "", $2); print}' file.txt
Exemplo:
% cat file.txt
gi_1 Dog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Pork;Black;White;Beige;Brown;Cyan;Purple;Red pepper
% awk -F '\t' -v OFS='\t' 'sub("^[^;]*;", "", $2)' file.txt
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
% awk -F '\t' -v OFS='\t' '$1 ~ /^gi_[[:digit:]]$/ {sub("^[^;]*;", "", $2); print}' file.txt
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
Uma solução generalizada usando grep com sabor Perl:
$ a="gi_1 \t Dog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish"
[s@SS data]$ echo $a | grep -P -o "((^gi_. \\t )|(?<=[; ])(?:.(?!(([; ].+)){8}))+$)" | sed ':a;N;$!ba;s/\n/ /g'
gi_1 \t Pink;Blue;Beige;Yellow;Orange;Red;Green irish
Note que isso funciona com qualquer número de palavras.
O grupo sem captura e a antecipação negativa excluem quaisquer caracteres que não sigam uma sequência repetida de [; ] seguido por quaisquer caracteres.
A antecipação positiva no começo é obtida do início [; \ t] personagem
A parte sed elimina a nova linha entre elas.
Com o GNU sed, podemos fazer isso procurando por 6 ponto e vírgula em uma estrutura de loop do-until.
sed -e '
:loop
s/\t[^;]*;/\t/
s/;/&/6
Tloop
' yourfile
Tags text-processing