Ordenação numericamente por posição do campo de caractere dentro do campo

1

Eu tenho um extrato de um arquivo de zona DNS avançada, que eu quero classificar por endereço IP crescente. Antes de marcar isso como uma duplicata, por favor, leia em pouco tempo, porque isso não é sobre a classificação de endereços IP como tal ( sort -k5V resolveria isso).

Aqui está uma amostra dos dados:

esx01.example.com.      3600    IN      A       10.1.1.212
ilo01.example.com.      3600    IN      A       10.1.1.211
nas01.example.com.      3600    IN      A       10.1.1.101
pc001.example.com.      1200    IN      A       10.1.1.42
pc002.example.com.      1200    IN      A       10.1.1.52
pc003.example.com.      1200    IN      A       10.1.1.29

Neste caso específico, sei que posso classificar apenas o último octeto, portanto, isso deve ser uma aplicação simples de sort .

A página man confirma que posso usar -k não apenas com um campo, mas também com um deslocamento dentro desse campo e com um modificador numérico n

KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where F is a field number and C a character position in the field; both are origin 1, and the stop position defaults to the line's end. If neither -t nor -b is in effect, characters in a field are counted from the beginning of the preceding whitespace. OPTS is one or more single-letter ordering options [bdfgiMhnRrV], which override global ordering options for that key.

O último octeto começa convenientemente no deslocamento de caractere oito dentro do quinto campo, então meu entendimento é que este comando deve ser suficiente:

sort -k5.8n /tmp/axfr.10.1.1

No entanto, isso não classifica meus dados. Empiricamente eu acho que preciso começar na posição de campo 15 para classificar esses dados em ordem numérica crescente como esperado:

sort -k5.15n /tmp/axfr.10.1.1

pc003.example.com.      1200    IN      A       10.1.1.29
pc001.example.com.      1200    IN      A       10.1.1.42
pc002.example.com.      1200    IN      A       10.1.1.52
nas01.example.com.      3600    IN      A       10.1.1.101
ilo01.example.com.      3600    IN      A       10.1.1.211
esx01.example.com.      3600    IN      A       10.1.1.212

Por quê?

    
por roaima 16.11.2017 / 16:25

2 respostas

3

Use a opção sort --debug para obter algumas dicas:

$ echo 'esx01.example.com.      3600    IN      A       10.1.1.212' | 
   sort --debug -k5.8n
sort: using simple byte comparison
sort: leading blanks are significant in key 1; consider also specifying 'b'
sort: key 1 is numeric and spans multiple fields
esx01.example.com.      3600    IN      A       10.1.1.212
                                                ____

Está sublinhando o campo de classificação. Não é o que você esperava. Você precisa de -b , pois a classificação conta as colunas do final do campo anterior (Página man: Se nem -t nem -b estiver em efeito, os caracteres em um campo serão contados a partir do início do espaço em branco precedente ):

$ ... | sort --debug -b -n -k5.8 
sort: using simple byte comparison
sort: key 1 is numeric and spans multiple fields
esx01.example.com.      3600    IN      A       10.1.1.212
                                                       ___

O -n precisa ser separado:

$ ... | sort --debug -b -k5.8n
sort: using simple byte comparison
sort: leading blanks are significant in key 1; consider also specifying 'b'
sort: key 1 is numeric and spans multiple fields
sort: option '-b' is ignored
esx01.example.com.      3600    IN      A       10.1.1.212
                                                ____

ou o b fornecido com o n :

$ ... | sort --debug  -k5.8nb
sort: using simple byte comparison
sort: key 1 is numeric and spans multiple fields
esx01.example.com.      3600    IN      A       10.1.1.212
                                                       ___
    
por 16.11.2017 / 16:35
0

Quando as especificações de campo do tipo (ou qualquer coisa) estão ficando descontroladas, ficando difíceis de construir e decodificar e depurar, pode ser mais produtivo e claro pré-processar os dados:

awk -F. '{print $NF"\t"$0}' | sort -snk1,1 | cut -f2-
    
por 16.11.2017 / 17:27

Tags