как распаковать строку в bash?

Мне нужно преобразовать строку в последовательность десятичного кода ascii с помощью команды bash.

пример: для строки 'abc желаемый вывод будет 979899
где a=97, b=98 и c=99 в десятичном коде ascii.

Я смог добиться этого с помощью шестнадцатеричного кода ascii, используя xxd.

printf '%s' 'abc' | xxd -p

что дает мне результат: 616263
где a=61, b=62 и c=63 в шестнадцатеричном коде ascii.

Есть ли эквивалент xxd, который дает результат в десятичном коде ascii вместо шестнадцатеричного кода ascii?


person Wiliam Carvalho    schedule 14.11.2019    source источник
comment
Что вы думаете о пунктуации? Символ u и последующие символы представлены тремя десятичными цифрами. Если они однажды объединены в прямую строку, вы не сможете восстановить исходную последовательность символов.   -  person tshiono    schedule 15.11.2019
comment
На самом деле мне не нужно извлекать исходную последовательность символов. Мне нужно воспроизвести алгоритм, сделанный в java, в сценарий оболочки, один из шагов алгоритма java делает то же самое, что я просил здесь.   -  person Wiliam Carvalho    schedule 15.11.2019
comment
xxd(1) справочная страница   -  person jww    schedule 15.11.2019


Ответы (3)


Если вы не возражаете, что результаты объединяются в строку, попробуйте следующее:

echo -n "abc" | xxd -p -c 1 |
while read -r line; do
    echo -n "$(( 16#$line ))"
done

Результат:

979899
person tshiono    schedule 15.11.2019
comment
Спасибо за ответ, я пробую здесь несколько вариантов, чтобы проверить, какой из них лучше подходит для моего решения. - person Wiliam Carvalho; 15.11.2019

Юникод Решение

Что делает эту проблему раздражающей, так это то, что вам нужно конвейеризировать символы при преобразовании из шестнадцатеричного в десятичное. Таким образом, вы не можете выполнить простое преобразование из char в hex в dec, поскольку некоторые шестнадцатеричные представления символов длиннее других.

Оба этих решения совместимы с Unicode и используют кодовую точку символа. В обоих решениях для ясности в качестве разделителя выбрана новая строка; измените это на '' без разделителя.

Баш

sep='\n'
charAry=($(printf 'abc????' | grep -o .))
for i in "${charAry[@]}"; do
  printf "%d$sep" "'$i"
done && echo
97
98
99
127926

Python (в Баше)

Здесь мы используем понимание списка, чтобы преобразовать каждый символ в десятичное число (ord), соединить его как строку и распечатать. sys.stdin.read() позволяет нам использовать встроенный Python для получения входных данных из канала. Если вы замените input на предполагаемую строку, это решение станет кросс-платформенным.

printf '%s' 'abc????' | python -c "
import sys
input = sys.stdin.read()
sep = '\n'
print(sep.join([str(ord(i)) for i in input]))"
97
98
99
127926

Изменить: если все, что вам нужно, это использовать шестнадцатеричный код независимо от кодировки, используйте ответ @user1934428

person Ross Jacobs    schedule 15.11.2019
comment
Спасибо за ответ, я пробую здесь несколько вариантов, чтобы проверить, какой из них лучше подходит для моего решения. - person Wiliam Carvalho; 15.11.2019

str=abc
printf '%s' $str | od -An -tu1

-An избавляется от адресной строки, которую обычно выводит od, а -tu1 обрабатывает каждый входной байт как целое число без знака. Обратите внимание, что предполагается, что один символ равен одному байту, поэтому он не будет работать с Unicode, JIS и т.п.

Если вам действительно не нужны пробелы в результате, передайте его дальше в tr -d ' '.

person user1934428    schedule 15.11.2019