Procurando linha por linha entre os dois primeiros jogos

6

Eu tenho o arquivo com texto:

1861_ASSET-D_T_201702181000-201702181045_HN_
197895_STRING-H_T_201702181000-201702181045_HN_
14512861_FILE-FD_T_201702181000-201702181045_HN

Como eu posso alocar texto entre primeira e segunda correspondências "_" usando egrep, awk ou sed?

Eu quero ter:

ASSET-D
STRING-H
FILE-FD
    
por Oleksii 20.02.2017 / 13:30

5 respostas

10

$ sed -r 's/[^_]+_([^_]+)_.*//' file
ASSET-D
STRING-H
FILE-FD

Explicação

  • -r Use ERE
  • s/old/new/ replace old com new
  • [^_]+ alguns caracteres que não são sublinhados
  • (some chars) save some chars para mais tarde
  • .* qualquer número de caracteres
  • do padrão salvo
por Zanna 20.02.2017 / 13:51
10

Você pode usar awk com os seguintes parâmetros:

  • -F "_" - que usa _ como separador
  • '{print }' - que imprime o segundo elemento

    $ awk -F  "_" '{print }' input_file
    ASSET-D
    STRING-H
    FILE-FD
    
por Yaron 20.02.2017 / 13:35
9

Se você quiser permitir outras ferramentas, cut seria a solução mais simples:

cut -d _ -f 2 < input.txt > output.txt
    
por David Foerster 20.02.2017 / 13:54
6

Um par de abordagens de perl:

$ perl -F_ -lae 'print $F[1]' file 
ASSET-D
STRING-H
FILE-FD

O -a faz o perl agir como awk, dividindo cada linha de entrada no caractere dado por -F e salvando cada campo resultante na matriz @F . Portanto, imprimir $F[1] imprimirá o segundo campo (as matrizes começam a contar em 0).

Alternativamente:

$ perl -pe 's/.*?_(.+?)_.*//' file 
ASSET-D
STRING-H
FILE-FD

O -p significa "imprimir todas as linhas de entrada depois de executar o script dado por -e sobre ele". O s/from/to/ é o operador de substituição. Ele substituirá from por to . Aqui, eu estou combinando 0 ou mais caracteres ( .* ), mas tornando-o "não-ganancioso" ( .*? ); que ? faz com que pare no menor tempo possível. Portanto, .*?_ corresponderá a todos até o primeiro _ . A próxima parte, (.+?)_ , corresponde a um ou mais caracteres até o próximo _ e depois combinamos todo o resto até o final da linha ( .* ). Os parênteses "capturam" a correspondência e a disponibilizam no lado de substituição do operador como . Portanto, a coisa toda apenas substituirá a linha inteira pelo que estiver dentro dos parênteses.

Você também pode fazer isso com grep :

$ grep -oP '^.*?_\K[^_]+' file 
ASSET-D
STRING-H
FILE-FD

O -o significa "imprimir apenas a parte de cada linha que correspondeu" e o -P ativa as Expressões Regulares Compatíveis com Perl (PCRE) que nos fornecem \K . O \K , por sua vez, significa "ignorar tudo combinado até este ponto". Isso significa que podemos usar o ^.*?_ para processar tudo até o primeiro _ e, em seguida, usar \K para descartá-lo para que não seja impresso. Então, precisamos apenas de quantos caracteres não- _ , como podemos encontrar ( [^_]+ ).

    
por terdon 20.02.2017 / 14:13
6

Como um verso de python:

python3 -c "[print(l.split('_')[1]) for l in open('f')]"

em que 'f' é seu arquivo, entre aspas, por exemplo:

python3 -c "[print(l.split('_')[1]) for l in open('/home/jacob/blub')]"

ASSET-D
STRING-H
FILE-FD

Explicação

for l in open('f')

lê f por linha e

l.split('_')[1]

divide a linha pelo delimitador _ , mantém a segunda string (índice [1] , onde [0] é o primeiro.

print(l.split('_')[1]) 

imprime posteriormente a string encontrada.

    
por Jacob Vlijm 20.02.2017 / 14:25