Como substituir tudo, exceto um padrão específico por sed?

2

Gostaria de substituir tudo, exceto meus :: ID e [ID2], mas não consegui encontrar uma maneira de fazer isso com sed e manter correspondência, alguma sugestão?

Por exemplo:

TRINITY_DN75270_c3_g2::TRINITY_DN75270_c3_g2_i4::g.22702::m.22702 [sample]

Eu gostaria de ter:

TRINITY_DN75270_c3_g2_i4[sample]

Alguma sugestão?

    
por gusa10 30.06.2017 / 21:50

4 respostas

2

Para uma determinada entrada, conforme fornecido, essa expressão sed parece fazer o que você pergunta:

$ cat input
'>TRINITY_DN75270_c3_g2::TRINITY_DN75270_c3_g2_i4::g.22702::m.22702 [sample]'
$ sed 's/^.*::\([A-Z_0-9a-z]*\)::.*\[\(.*\)\].*/[]/' input
TRINITY_DN75270_c3_g2_i4[sample]

A mágica está em usar grupos de expressões regulares e duas referências anteriores para reconstruir a saída desejada. Para expor:

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  ^                        the beginning of the string
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))
  ::                       '::'
  \(                       group and capture to :
    [A-Z_0-9a-z]*            any character of: 'A' to 'Z', '_', '0'
                             to '9', 'a' to 'z' (0 or more times
                             (matching the most amount possible))
  \)                       end of 
  ::                       '::'
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))
  \[                       '['
  (                        group and capture to :
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
  )                        end of 
  \]                       ']'
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))

Portanto, é a primeira chave que você deseja extrair e é o que estiver nas chaves quadradas depois disso. Is é então reconstruído por []/ , criando o resultado desejado.

    
por 30.06.2017 / 21:59
2
sed -e '
   s/::/\n/; s//\n/
   s/.*\n\(.*\)\n.*\(\[[^]]*]\).*//
' data

Marcamos o ID substituindo o :: que ocorre no 1º & Segunda vez. Então tiramos tudo, exceto a região marcada + região

Resultados:

TRINITY_DN75270_c3_g2_i4[sample]
    
por 30.06.2017 / 22:11
2

awk alternativa:

awk -F'::' '{ match($NF,/\[.+\]/); print $2 substr($NF,RSTART,RLENGTH) }' file

A saída:

TRINITY_DN75270_c3_g2_i4[sample]
  • -F'::' - considerando :: como separador de campo
por 30.06.2017 / 22:12
1

Supondo que você gostaria de manter o segundo campo entre os :: separadores + [sample] , então apagando tudo antes e depois do campo até o último espaço você poderia:

sed 's/^[^:]*::\([^:]*\)::.* //'  

Isto irá combinar desde o início da linha até o último espaço ( .* é "ganancioso"), e substituí-lo apenas pelo primeiro "sub" -expressão "(marcada com parênteses escapados).

Para mais detalhes sobre backreferences e sub-expressões, veja esta descrição no gnu. org .

    
por 30.06.2017 / 22:05

Tags