tl; dr - см. "заключение" в самом конце.
То, что здесь происходит, довольно интересно.
Прежде всего, echo -e
действует так (от man 1 echo
):
\0NNN
байт с восьмеричным значением NNN
(от 1 до 3 цифр)
Это означает, что 0
в \037
- это не восьмеричная цифра, это просто часть префикса \0
которая указывает последовательный восьмеричный ввод. Ваш \037
может быть \0037
и теперь только второй 0
является восьмеричной цифрой.
Все еще в пределах echo -e
\061
эквивалентно \0061
. Это эквивалентно 1
, буквальному символу, означающему "один".
Теперь кажется, что часть вывода strace
вы хотите декодировать, должна быть декодирована следующим образом:
write(1, "\0371", 21)
^ prefix that indicates consecutive octal output
^^^ three digits of octal output
^ literal character meaning "one"
Таким образом, префикс здесь не \0
а \
.
Вы используете printf "%b" "\0371"
. Общая форма - это printf FORMAT [ARGUMENT]…
и вот что man 1 printf
говорит о FORMAT
являющемся %b
:
%b
ARGUMENT
как строка с интерпретируемыми \
escapes, за исключением того, что восьмеричные escape-символы имеют форму \0
или \0NNN
Как видите, префикс \0
, как в echo -e
. Интерпретация теперь выглядит так:
printf "%b" "\0371"
^^ prefix that indicates consecutive octal input
^^^ three octal digits
Это объясняет ваш неправильный результат. Однако в том же руководстве говорится, что восьмеричные цифры в FORMAT
интерпретируются несколько иначе:
\NNN
байт с восьмеричным значением NNN
(от 1 до 3 цифр)
Префикс \
точно такой же, как в выводе strace
. Кроме того, кажется, что strace
заботится всякий раз, когда следующий символ может быть интерпретирован как восьмеричная цифра. Для сравнения:
$ strace -e write echo -ne '\037'
write(1, "\37", 1) = 1
+++ exited with 0 +++
в
$ strace -e write echo -ne '\037\101'
write(1, "\37A", 21) = 2
+++ exited with 0 +++
в
$ strace -e write echo -ne '\037\061'
write(1, "\0371", 21) = 2
+++ exited with 0 +++
Обратите внимание на ведущий 0
в последнем случае. Это нужно, чтобы избежать \371
который будет интерпретирован как один байт.
Похоже, что вы могли бы использовать printf
для декодирования вывода strace
, но вы должны передать его как FORMAT
, а не ARGUMENT
:
$ printf "\0371" | xxd -p
1f31
Но тогда другие последовательности, интерпретируемые внутри FORMAT
(например, %b
), доставят вам неприятности, поэтому лучше придерживаться ARGUMENT
. Я играл с sed
чтобы превратить \
в \0
в соответствующих случаях, это стало громоздким быстро; затем я понял, что %b
как FORMAT
также будет интерпретировать другие последовательности в ARGUMENT
! По моему это тупик.
Вывод: лучше изменить поведение strace
. Попробуйте шестнадцатеричный вывод:
$ strace -xx -e write echo -ne '\037\061'
write(1, "\x1f\x31", 21) = 2
+++ exited with 0 +++
затем
$ printf "%b" "\x1f\x31" | xxd -p
1f31