Exclua todas as linhas que não possuem n caracteres antes do delimitador

11

Eu tenho um arquivo de texto muito longo (a partir daqui ) que deve conter 6 caracteres hexadecimais e, em seguida, uma 'quebra' (que aparece como um caractere e não parece ser exibida corretamente na marcação de código abaixo) seguida por algumas palavras:

00107B  Cisco Systems, Inc
00906D  Cisco Systems, Inc
0090BF  Cisco Systems, Inc
5080    Cisco Systems, Inc
0E+00   ASUSTek COMPUTER INC.
000C6E  ASUSTek COMPUTER INC.
001BFC  ASUSTek COMPUTER INC.
001E8C  ASUSTek COMPUTER INC.
0015F2  ASUSTek COMPUTER INC.
2354    ASUSTek COMPUTER INC.
001FC6  ASUSTek COMPUTER INC.
60182E  ShenZhen Protruly Electronic Ltd co.
F4CFE2  Cisco Systems, Inc
501CBF  Cisco Systems, Inc

Eu olhei em volta e não consigo ver algo que funcionaria nessa situação. Minha pergunta é: como posso usar grep/ sed/ awk/ perlpara excluir todas as linhas deste arquivo de texto que não iniciam exatamente com 6 caracteres hexadecimais e, em seguida, um 'intervalo'?

PS Para pontos de bônus, qual é a melhor maneira de classificar o arquivo alfabeticamente e numericamente de acordo com os caracteres hexadecimais (ou seja, 000000-> FFFFFF)? Devo apenas usar sort?

Rocco
fonte

Respostas:

13
$ awk '$1 ~ /^[[:xdigit:]]{6}$/' file
00107B  Cisco Systems, Inc
00906D  Cisco Systems, Inc
0090BF  Cisco Systems, Inc
000C6E  ASUSTek COMPUTER INC.
001BFC  ASUSTek COMPUTER INC.
001E8C  ASUSTek COMPUTER INC.
0015F2  ASUSTek COMPUTER INC.
001FC6  ASUSTek COMPUTER INC.
60182E  ShenZhen Protruly Electronic Ltd co.
F4CFE2  Cisco Systems, Inc
501CBF  Cisco Systems, Inc

Isso usa awkpara extrair as linhas que contêm exatamente seis dígitos hexadecimais no primeiro campo. O [[:xdigit:]]padrão corresponde a um dígito hexadecimal e {6}requer seis deles. Juntamente com a ancoragem no início e no final do campo com ^e $respectivamente, isso corresponderá apenas às linhas desejadas.

Redirecione para algum arquivo para salvá-lo com um novo nome.

Note que isso parece funcionar com o GNU awk(comumente encontrado no Linux), mas não com, awkpor exemplo, no OpenBSD ou mawk.


Uma abordagem semelhante com sed:

$ sed -n '/^[[:xdigit:]]\{6\}\>/p' file
00107B  Cisco Systems, Inc
00906D  Cisco Systems, Inc
0090BF  Cisco Systems, Inc
000C6E  ASUSTek COMPUTER INC.
001BFC  ASUSTek COMPUTER INC.
001E8C  ASUSTek COMPUTER INC.
0015F2  ASUSTek COMPUTER INC.
001FC6  ASUSTek COMPUTER INC.
60182E  ShenZhen Protruly Electronic Ltd co.
F4CFE2  Cisco Systems, Inc
501CBF  Cisco Systems, Inc

Nesta expressão, \>é usado para corresponder ao final do número hexadecimal. Isso garante que números mais longos não sejam correspondidos. O \>padrão corresponde ao limite de uma palavra , ou seja, o espaço de largura zero entre um caractere de palavra e um caractere que não é de palavra.


Para classificar os dados resultantes, basta canalizar o resultado sort, ou sort -fse seus números hexadecimais usarem letras maiúsculas e minúsculas

Kusalananda
fonte
1
Perfeito, muito obrigado. Exatamente o que eu estava procurando!
Rocco
8

E, para completar, você também pode fazer isso com o grep:

$ grep -E '^[[:xdigit:]]{6}\b' oui.txt 
00107B  Cisco Systems, Inc
00906D  Cisco Systems, Inc
0090BF  Cisco Systems, Inc
000C6E  ASUSTek COMPUTER INC.
001BFC  ASUSTek COMPUTER INC.
001E8C  ASUSTek COMPUTER INC.
0015F2  ASUSTek COMPUTER INC.
001FC6  ASUSTek COMPUTER INC.
60182E  ShenZhen Protruly Electronic Ltd co.
F4CFE2  Cisco Systems, Inc
501CBF  Cisco Systems, Inc
$ 

Essa expressão grep estendida procura exatamente 6 dígitos hexadecimais no início de cada linha, seguida imediatamente por um limite que não seja de espaço em branco para espaço em branco ( \b).

Trauma Digital
fonte