Друкуючи десяткові символи до символів ascii, моя команда не виводиться за призначенням


14

Я хотів вивести рядок усіх символів ascii за допомогою наступної команди

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

Вихід з вищевказаної команди:

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

Це перша (зліва) цифра кожного числа.

Переглядаючи цей сайт, я натрапив на відповідь на свою проблему Як надрукувати всі друковані символи ASCII в CLI? Однак я все ще не розумію, чому мій оригінальний фрагмент не видає символи ascii за призначенням.


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

7
В bashі zshце може бути зроблено без петлі і без зовнішньої команди: printf $(printf '\%o' {32..127}).
манастирство

@manatwork: точно так ... дякую за його вказівку ..
pradeepchhetri

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використовується. Використання восьмеричних чисел відрізняється від використання однобайтових символів.
Ділан

3

%c Інтерпретується пов'язаний аргумент як char: друкується лише перший символ даного аргументу

Здається, у вас вже є спосіб їх надрукувати, але ось один варіант.

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

0

Вам потрібно printf, але лише один раз; ви можете замінити одне використання printfбільш простим та ефективним echoплюс послідовності втечі 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.