Неожиданная обратная косая черта при преобразовании из шестнадцатеричного в двоичное число

Полная честь @steeldriver за то, что он предположил, что это проблема с завершением строки возврата каретки, и дань уважения @AlexP за предложение hexdump как способ проверки теории.

Проблема в том, что строка, возвращаемая arduino-serial, имела завершающий '\ r \ n' (он же 0x0d 0x0a), о чем свидетельствует hexdump:

echo "$VERS" | hexdump -C
00000000  30 30 2e 30 31 0d 0a                              |00.01..|

Одно из возможных исправлений, которое я выбрал, - это конвейерная передача результаты через tr -c '\ r' для удаления возвращаемого символа, поэтому результирующий скрипт выглядит следующим образом:

#!/bin/bash

ARDUINO_SERIAL=arduino-serial/arduino-serial
PORT="/dev/cu.usbmodem1421"

VERS=$($ARDUINO_SERIAL -q -b 9600 -p $PORT -S 'V' -e '\r' -r | tr -d '\r')
echo --- VERS = $VERS
B="hello${VERS}goodbye"
echo --- B = $B

, который печатает как ожидалось:

--- VERS = 00.01
--- B = hello00.01goodbye
1
13.10.2016, 21:48
3 ответа

Если GNU bc недоступен, это также работает :

echo "ibase=16; obase=2; 3D3D516343746D4D6D6C315669563362" | \
    bc | tr -d '\\\n' ; echo
111101001111010101000101100011010000110111010001101101010011010110110101101100001100010101011001101001010101100011001101100010

(Слишком длинный вывод намеренно не упакован.)

0
27.01.2020, 23:25

Реализация POSIX bc разбивает выходные строки на максимум 70 символов, используя обратную косую черту в качестве символа продолжения строки .

Если у вас GNU-версия bc , вы можете изменить это поведение, используя переменную среды BC_LINE_LENGTH , например

$ printf 'ibase=16; obase=2; %s\n' 3D3D516343746D4D6D6C315669563362 | BC_LINE_LENGTH=0 bc
111101001111010101000101100011010000110111010001101101010011010110110101101100001100010101011001101001010101100011001101100010

Из info bc :

'BC_LINE_LENGTH'
     This should be an integer specifying the number of characters in an
     output line for numbers.  This includes the backslash and newline
     characters for long numbers.  As an extension, the value of zero
     disables the multi-line feature.  Any other value of this variable
     that is less than 3 sets the line length to 70.
2
27.01.2020, 23:25

Вы можете фильтровать вывод, используя некоторые "башизмы": echo ${BIN//[$'\r\n\\\']}

пример:

for i in 3D3D516343746D4D6D6C315669563362; do BIN=$(echo "ibase=16; obase=2; $i" | bc); echo ${BIN//[$'\r\n\\']};done

Вы также можете использовать переменную env BC_LINE_LENGTH, которую GNU bc будет использовать для настройки длины строки (0 - неограниченно).

пример:

for i in 3D3D516343746D4D6D6C315669563362; do BIN=$(echo "ibase=16; obase=2; $i" | BC_LINE_LENGTH=0 bc ); echo $BIN;done

1
27.01.2020, 23:25

Теги

Похожие вопросы