Печать десятичного знака в символ ascii, моя команда не выводит, как задумано

14

Я хотел вывести строку всех символов ascii с помощью следующей команды

for i in `seq 32 127`; do printf "%c" $i; done

Вывод вышеуказанной команды:

33333334444444444555555555566666666667777777777..............

Это первая (слева) цифра каждого числа.

Просматривая этот сайт, я наткнулся на ответ на мою проблему. Как напечатать все печатные символы ASCII в CLI? Однако я до сих пор не понимаю, почему мой оригинальный фрагмент не выводит символы ascii, как предполагалось.

Ifthikhan
источник
1
POSIX диктует это, вот comp.unix.shellветка о том, почему это правильно;)
sr_
@sr_ Спасибо за указание на тему. Это было объяснение, которое я искал.
Ифтихан

Ответы:

13

Вы не можете напрямую распечатать коды ASCII, используя printf "%c" $iкак в C.

Сначала вы должны преобразовать десятичное значение i в восьмеричное значение, а затем распечатать его, используя printfи поставив \перед ними восьмеричные значения.

Чтобы напечатать A, вы должны преобразовать десятичное 65 в восьмеричное, то есть 101, и затем вы должны напечатать это восьмеричное значение как:

printf "\101\n"

Это напечатает A.

Таким образом, вы должны изменить его на:

for i in `seq 32 127`; do printf \\$(printf "%o" $i);done;

Но с помощью awkвы можете напрямую печатать как на языке Си

awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo
pradeepchhetri
источник
7
В bashи zshэто может быть сделано без петли и без внешней команды: printf $(printf '\%o' {32..127}).
manatwork
@manatwork: да, точно ..
большое спасибо
1
@pradeepchhetri: Спасибо за подробный ответ, и он, похоже, охватывает большинство необходимых деталей (поэтому я выбираю ваш ответ). Однако, я думаю, он упустил важную информацию, которую можно найти в следующем сообщении на unix.derkeiler.com/Newsgroups/comp.unix.shell/2007-07/… . В нем говорится, что «операнды аргумента должны рассматриваться как строки, если соответствующий спецификатор преобразования равен b, c или s ...»
Ifthikhan
Это не (char)(127)забой или что-то в этом роде. Что бы это ни было, оно выглядит как один из шестиугольников или как их там называют. Если вы хотите только «печатный» (то есть читаемый), просто перейдите к 126. Кроме того, хорошая мысль с восьмеричным. Это умно; Я думал с точки зрения шестнадцатеричного (например printf '\x%x; {32..126}... или 127, я думаю, так как все вы тоже это сделали), но это не работает. Октал спасает день! :) Наконец, @Ifthikhan, я не уверен, что ты имеешь в виду. awkчасто использует команды в стиле C и больше нигде не %cиспользуется. Использование восьмеричных чисел отличается от использования однобайтовых символов.
Дилан
3

%c Интерпретирует связанный аргумент как char: печатается только первый символ данного аргумента

Кажется, у вас уже есть способ напечатать их, но вот один из вариантов.

for i in `seq 32 127`; do printf "\x$(printf "%x" $i) $i"; done
Peter.O
источник
0

Вам нужно printf, но только один раз; Вы можете заменить одно использование printfна более простую и эффективную, echoа также escape-последовательность Bash:

С шестнадцатеричными числами:

for i in `seq 32 127`; do
  echo -ne \\x$(printf %02x $i)
done

С восьмериками:

for i in `seq 32 127`; do
  echo -ne \\0$(printf %03o $i)
done
Luchostein
источник