tl; dr - см. «заключение» в самом конце.
То, что здесь происходит, довольно интересно.
Прежде всего echo -e
действует так (с man 1 echo
):
\0NNN
байт с восьмеричным значениемNNN
(от 1 до 3 цифр)
Это означает, что 0
in \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
как строка с\
интерпретируемыми экранированными символами, за исключением того, что восьмеричные экранированные символы имеют форму\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