bc binário de saída como nibbles separados por espaços em branco

3

Estou depurando código que contém algumas operações de mudança de bit, e estou usando muito bc para ver o que está acontecendo no nível de bit.

Veja o que eu uso:

$ echo 'obase=2;598980975283696640' | bc
100001010000000000100000011000000011000000000111010000000000

Existe uma maneira simples de obter a saída como nibbles separados por espaços em branco? Por exemplo,

1000 0101 0000 0000 0010 0000 0110 0000 0011 0000 0000 0111 0100 0000 0000

Agradecemos antecipadamente por suas respostas!

Editar: Obrigado pelas respostas! No entanto,

Eu tentei em outro número, 262148.

Deve ser:

100 0000 0000 0000 0100

Mas é:

1000 0000 0000 0000 100

Eu acho que o script tem que pesquisar para trás através da string para acertar?

    
por vindarmagnus 01.01.2015 / 21:00

8 respostas

2

Eu usaria essa função simples:

nibbles () { echo "obase=2; $1" | bc | rev | while read -n4 a; do echo -n "$a ";done | rev ; echo; }

$ nibbles 598980975283696640
1000 0101 0000 0000 0010 0000 0110 0000 0011 0000 0000 0111 0100 0000 0000 
    
por 01.01.2015 / 21:15
7
echo 'obase=2;598123123980975281233696640' | BC_LINE_LENGTH=0 bc |
  rev | fold -w4 | paste -sd ' ' - | rev

Ou:

echo 'obase=2;598123123980975281233696640' | BC_LINE_LENGTH=0 bc | sed ':1
  s/\(.*[01]\)\([01]\{4\}\)/ /;t1'

BC_LINE_LENGTH=0 é para parar bc dos números de empacotamento em 70 colunas. Isso é específico do GNU. rev não é um comando padrão, mas bastante comum.

    
por 01.01.2015 / 21:48
1

Com o GNU awk :

awk '{while(length%4)$0=0$0;$1=$1}1' FPAT=....

Entrada

100001010000000000100000011000000011000000000111010000000000
1000000000000000100

Saída

1000 0101 0000 0000 0010 0000 0110 0000 0011 0000 0000 0111 0100 0000 0000
0100 0000 0000 0000 0100
    
por 02.01.2015 / 10:29
0

Como alternativa, você pode usar o shell interativo do Python para ele. Por exemplo:

$ python
>>> s = bin(598980975283696640)[2:]; s = '0'*(4-len(s)%4)*(len(s)%4>0)+s
>>> [s[i:i+4] for i in range(0, len(s), 4)]
['1000', '0101', '0000', '0000', '0010', '0000', '0110', '0000',
 '0011', '0000', '0000', '0111', '0100', '0000', '0000']
>>> s = bin(5989809752836966)[2:]; s = '0'*(4-len(s)%4)*(len(s)%4>0)+s
>>> [s[i:i+4] for i in range(0, len(s), 4)]
['0001', '0101', '0100', '0111', '1011', '0011', '0100', '0010',
 '1001', '0111', '0000', '1011', '0110', '0110']

Ou por apenas um disparo:

$ python -c 's = bin(598980975283696640)[2:]; s = '0'*(4-len(s)%4)*(len(s)%4>0)+s; print [s[i:i+4] for i in range(0, len(s), 4)]' 
['1000', '0101', '0000', '0000', '0010', '0000', '0110', '0000', '0011', '0000', '0000', '0111', '0100', '0000', '0000']
    
por 01.01.2015 / 21:24
0

Você pode aplicar (GNU) cut à saída de bc usando um delimitador de saída personalizado:

$ echo 'obase=2;5989809752836966' | BC_LINE_LENGTH=0 bc | rev \
  | cut --output-delimiter=' ' \
     -c$(echo -n 1-4; for i in $(seq 5 4 100); do echo -n ,$i-$((i+3)); done ) \ 
  | rev
1 0101 0100 0111 1011 0011 0100 0010 1001 0111 0000 1011 0110 0110

A construção da cut LIST fornecida via -c explora o fato de que partes não usadas dessas listas não são relatadas como um erro.

Uma versão dc :

$ echo '5989809752836966 2 o p' | DC_LINE_LENGTH=0 dc | rev \
  | cut --output-delimiter=' ' \
     -c$(echo -n 1-4; for i in $(seq 5 4 100); do echo -n ,$i-$((i+3)); done ) \
  | rev  
1 0101 0100 0111 1011 0011 0100 0010 1001 0111 0000 1011 0110 0110
    
por 01.01.2015 / 22:45
0

O meu caminho preferido seria preenchê-lo com múltiplos de quatro:

echo 'obase=2;262148'| bc | perl -pe 'chomp; $_ = 0 x ((-length) % 4) . $_;s/([01]{4})/ $1/g;s/$/\n/'
    
por 01.01.2015 / 21:15
0
echo 'obase=2;262148' | bc |
   perl -E 'say readline 
                =~ s/((....)*)\n/ $1/r 
                =~ s/(\d{4})/$1 /gr'
    
por 02.01.2015 / 03:42
0

Deixa bc e sed fazer a divisão em nibbles para você e usa bc e printf para fazer a conversão em binário de 4 dígitos com 0 dígitos:

i=598980975283696640
echo "obase=16;$i" | bc | sed 's/./&\n/g' | \
  xargs -I {} sh -c 'echo "ibase=16;obase=2;{}" | bc' | \
  xargs printf "%04d "
echo

1000 0101 0000 0000 0010 0000 0110 0000 0011 0000 0000 0111 0100 0000 0000
    
por 02.01.2015 / 06:13

Tags