Verificador de seqüência numérica hexadecimal no Linux?

1

Eu tenho uma lista de números hexadecimais. Eu gostaria de verificar se eles estão em seqüência ou não. Ou seja, eles devem ser números consecutivos, em ordem crescente. Em outras palavras, deve haver um incremento de 1 de cada linha para a próxima.

Lista de exemplos de números hexadecimais:

85AF
85B0
85B1
85B2
85B3
85B4
85B5
85B6
85B7
85B8
85B9
85BA
85BB
85BC
85BD
85BE
85BF
85C0

Na realidade, eu teria mais de 500 números para verificar.

Saída desejada:

All numbers are in sequence
     (or)
Numbers are not in sequence.

Isso está no Solaris, com o ksh.

    
por ayrton_senna 18.05.2015 / 19:18

6 respostas

2

O Awk pode fazer isso facilmente se a saída estiver em decimal, mas não é possível analisar números hexadecimais (pelo menos o awk padrão não pode, algumas versões como o GNU awk podem). Você pode usar bc para fazer a conversão. Isso funciona em todos os sistemas POSIX.

{ echo "ibase=16"; cat input.txt; } | bc |
awk 'NR==1 {origin = $0-1}
     $0!=origin+NR {print "Out-of-sequence number at line", NR; exit(1)}' >&2
    
por 19.05.2015 / 01:30
2

Como dito em outra resposta, seria bom fazer isso no awk, mas o antigo awk (provavelmente disponível no Solaris) não entende números hexadecimais.

Uma solução rápida é usar wc -l e alguma matemática ksh:

#! /bin/ksh

first="0x$(head -n1 infile)"
last="0x$(tail -n1 infile)"
lines=$(wc -l <infile)

if [[ "$(( last - first + 1 - lines ))" -eq 0 ]]; then
    echo "All numbers are in sequence."
else
    echo "Numbers are not in sequence."
fi
    
por 28.09.2018 / 03:40
1

Aqui está uma opção:

while read x; do echo $((16#$x)); done <yourfile | awk 's && $1!=s+1{exit(1)}{s=$1}'

Este comando shell irá produzir um status de saída de 1 (em caso de falha) e 0 (em caso de sucesso). Este comando pode ser usado, e. em uma cláusula if como a seguinte para produzir a saída desejada:

if  while read x; do echo $((16#$x)); done < yourfile | awk 's && $1!=s+1{exit(1)}{s=$1}'
then echo All numbers are in sequence
else echo Numbers are not in sequence
fi

(Note que você tem que substituir o nome "yourfile" pelo nome do arquivo que contém sua seqüência numérica hexadecimal.)

Você também pode omitir o loop do shell e usar a opção awk do GNU -n para processar os números hexadecimais diretamente:

if  sed 's/^/0x/' <yourfile | awk -n 's && $1+0!=s+1{exit(1)}{s=$1+0}'
then echo All numbers are in sequence
else echo Numbers are not in sequence.
fi

Nota: sed é usado aqui para criar o formato sintaticamente esperado para os números hexadecimais (com o primeiro 0x ).

    
por 18.05.2015 / 20:14
0

Você pode usar sort com a opção -c para verificar se os dados de entrada estão classificados:

-c

Check that the single input file is ordered as specified by the arguments and the collating sequence of the current locale. Output shall not be sent to standard output. The exit code shall indicate whether or not disorder was detected or an error occurred. If disorder (or, with -u, a duplicate key) is detected, a warning message shall be sent to standard error indicating where the disorder or duplicate key was found.

Então, um simples

LC_ALL=C \
sort -c data 2> /dev/null \
&& echo All numbers are in sequence \
|| echo Numbers are not in sequence

faria.

    
por 18.05.2015 / 21:01
0

Se você quiser uma sequência estrita, isso pode ser feito facilmente pela sequência de etalon do produto e compará-lo com o arquivo

[ $(comm --nocheck-order -3 \
     <(sed '/\S/!d' file) \
     <(printf "%X\n" \
          $(seq $((16#$(sed '/./!d;q' file))) \
                $((16#$(tac file|sed '/./!d;q')))))) ] &&
echo 'Numbers are not in sequence' ||
echo 'All numbers are in sequence'

Apenas para verificar se todos os números são hexadecimais:

sed '/^[[:xdigit:] ]*$/!{
        s/.*/Numbers are not in sequence: &/
        q
                        }
     $! d
     s/.*/All numbers are in sequence/' hexadecimal_number.list
  • /^[[:xdigit:] ]*$/ verifica se na linha existem símbolos hexadecimais e apenas espaço (ou nada - linha vazia)
  • ! reverse match, então execute comandos em {} apenas se houver algum outro símbolo que não o descrito acima
  • s/.*/.../;q s ustituir toda a linha por Numbers are not in sequence do que q uit script com linha de impressão
  • $! d se o script não executou anterior (correspondência de padrão) e se a linha não for a última d elete inicia com a próxima linha
  • s/.*/.../ se o script chegar na última linha (para que todas as linhas correspondam ao padrão) s ubstitute última linha por All numbers are in sequence uma impressão
por 18.05.2015 / 19:48
0

Dado o arquivo de entrada hexlist.txt , isso funciona em ksh e bash . Ele usa o numinterval util. Se numinterval não estiver disponível, remova o comentário da função de falsificação:

# fake 'numinterval' function
# numinterval() { printf '%s %s r - p\n' $(sed '1!{$!p}') | dc ; }

n=; eval printf '%s\n' $(printf '$((16#%s\n)) ' $(<hexlist.txt)) | 
numinterval | grep -qw 1 || n=not ; echo All numbers are $n in sequence
    
por 27.09.2018 / 22:22