Imprime 2 padrões diferentes de uma string em uma linha

5

Eu tenho um arquivo com strings como o abaixo.

F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315

As cadeias são demarcadas pelos marcadores, neste caso, o "F" e um número. Nesse caso, os marcadores são F1 , F2 , F3 , F4 , F5 , F6 e F7 .

Gostaria de imprimir os 5 caracteres seguintes F2 e os 6 caracteres seguintes F6 separados por um espaço para que o resultado seja

B3094 BC313D

Aqui está minha tentativa embora imprima em duas linhas em vez de uma. Como gostaria de ambos os valores em uma linha.

$ echo F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315 | \
   awk '{match($0,/F2/); print substr($0, RSTART +2, RLENGTH +3);} \
        {match($0,/F6/); print substr($0, RSTART +2,RLENGTH +4);}'
    
por Allan GItobu 17.07.2018 / 01:13

3 respostas

5

Você está super perto de uma solução de trabalho. Aqui está uma maneira de fazê-lo (formatado para legibilidade):

awk '{
    match($0,/F2/); 
    a=substr($0, RSTART +2, RLENGTH +3); 
    match($0,/F6/); 
    b=substr($0, RSTART +2,RLENGTH +4);
    print a" "b
}'

Nesse caso, estou pegando as duas funções substr() e atribuindo-as às variáveis, em vez de imprimi-las diretamente e, em seguida, configurando-as para imprimir ao mesmo tempo no final. Ao imprimi-los em uma única chamada de impressão, awk adiciona apenas um único caractere de nova linha no final da linha, em vez de após cada parte da linha, que é o que dividia seu resultado em duas linhas.

bash:~$ echo F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315 | awk '{match($0,/F2/); a=substr($0, RSTART +2, RLENGTH +3); match($0,/F6/); b=substr($0, RSTART +2,RLENGTH +4); print a" "b}'
B3094 BC313D
    
por 17.07.2018 / 01:30
3

Se você sabe que os marcadores Fn estão ordenados, poderá usá-los como separadores de campo:

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    awk -F'(F2|F6)' '{print substr($2,1,5), substr($3,1,6)}'
B3094 BC313D

ou dividindo todos os marcadores Fn e numerando os campos de acordo

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    awk -F'F[0-9]' '{print substr($3,1,5), substr($7,1,6)}'
B3094 BC313D

(neste caso, você pode não precisar do substr , se quiser tudo até o próximo Fn - não está claro na descrição do seu problema).

Com o GNU Awk, você pode capturar as duas substrings em um único padrão e acessá-las por meio da matriz opcional match :

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    gawk 'match($0, /F2(.{5}).*F6(.{6})/, a) {print a[1], a[2]}'
B3094 BC313D

Alternativamente, com Perl você poderia capturar os caracteres depois dos marcadores usando lookbehinds:

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    perl -lne 'print join " ", /(?<=F2).{5}|(?<=F6).{6}/g'
B3094 BC313D

ou

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    perl -lne 'print "$1 $2" if /(?<=F2)(.{5}).*?(?<=F6)(.{6})/g'
B3094 BC313D
    
por 17.07.2018 / 02:52
0
perl -lne ' $, = $"; print /(?=.*F2(.{5}))(?=.*F6(.{6}))/' input-file.txt

O texto acima, independentemente de qual seja, F2 ou F6 será anterior no registro atual, imprimirá os seguintes dígitos de F2 , em seguida, os de F6 .

$, = OFS $" = double quoted separator = single space

    
por 17.07.2018 / 10:14

Tags