Remove todas as palavras antes de um padrão específico, depois de outro padrão

1

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.

    
por Annick Raymond 12.06.2017 / 17:39

4 respostas

1

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
por 12.06.2017 / 18:09
0

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
    
por 12.06.2017 / 17:49
0

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.

    
por 12.06.2017 / 18:34
0

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
    
por 12.06.2017 / 22:44