Чому роздільний пристрій (ASCII 31) невидимий у клемному виході?


17

Символьний роздільник символів ASCII (ASCII 31, вісімка 37) видно у Vim як ^_. Але якщо я надрукую той самий файл до терміналу, символ невидимий. Це призводить до того, що поля в рядку злипаються:

# In Vim and less:

first field^_second field^_last field

# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field

# print 2nd field with awk 
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field

Я думаю, що я можу зробити роздільник блоків видимим за допомогою cat -v:

cat -v delim.txt
first field^_second field^_last field

Але це досить громіздко. Чому роздільник блоків не має видимого зображення при друкуванні до stdout в оболонці Bash? Я навіть не можу правильно скопіювати та вставити вихід оболонки; сепаратор блоку втрачається в процесі.


Не всі символи можна друкувати, роздільник одиниць - один із них. Деякі редактори відображають його певним чином, щоб зробити можливим редагування. Вам потрібно перекласти його в послідовність символів для друку, а може бути, іншого шрифту / кольору, щоб зменшити неоднозначність.
ctrl-alt-delor

3
Коди ASCII під 31 і 127 призначені для того, щоб викликати термінал або пристрій щось робити (звідси їх називають контрольними кодами) або виступати за щось у протоколі (наприклад, EOT або SOH), на відміну від відображення чогось. Він чує, коли термінали були пристроями, подібними до машинок, і фізично потрібні речі, такі як повідомлення телевізора до повернення вагона. Редактори можуть вирішити відображати їх, використовуючи позначення "^", оскільки ви щось редагуєте, і не хочуть, щоб термінал фактично робив те, що запитують контрольні коди.
ЛоуренсC

1
@LawrenceC: Код 127 насправді мав на меті змусити термінал нічого не робити. Якщо хтось пробивав стрічку і помилявся, натиснув би кнопку, щоб створити резервну копію стрічки одним пробілом і натиснути "протерти". вісім отворів. Коли читач зіткнувся з перфорованим символом, він надішле його по дроту, але одержувач може просто проігнорувати його.
supercat

Відповіді:


19

USСимвольний розділювач одиниць ( ), також відомий як IS1, знаходиться в cntrlкласі символів і не знаходиться в printкласі символів. Це контрольний символ, який призначений для організації тексту в групи, для програм, призначених для використання цієї інформації . Взагалі, символи, що не друкуються, ймовірно, будуть інтерпретовані та надані по-різному в різних програмах чи середовищах.

Причина, по якій ви бачите його як ^_у Vim, полягає в тому, що Vim - це інтерактивний редактор. Він може вільно рендерувати символи, що не можна друкувати, але хоче, доки правильний бінарний символ записується на диск.

Ви не можете отримати таку саму поведінку в оболонці, оскільки програми оболонок Unix написані для роботи та передачі простого тексту один одному. Коли ви catстворюєте файл, текст, який записується в термінал, повинен бути тим, що є насправді у файлі.

Так що це залишає термінальному пристрою для інтерпретації символу. І виходить, що деякі емулятори терміналу роблять візуалізації USперсонажа в відміну від інших. У gnome-terminal(або будь-якому vteтерміналі, що базується), символ буде представлений у вигляді поля, що містить шістнадцятковий код 001F. У xtermабо rxvtперсонаж справді невидимий.


Ну, я б не сказав, що USце абсолютно непомітно. Коли я вставляю цей символ у термінал з Ctrl+/(підтверджено через <C-v><C-/>), він видаляє непередбачувану кількість тексту на рядку. Я не повністю розумію його поведінку, але, здається, в основному це має якийсь ефект "зворотної вкладки", де замість того, щоб вставляти кількість пробілів, вона видаляє ряд символів, але потім іноді випадково вставляє текст, тож це заплутано .
Бреден Кращий

10

Розділювач блоків знаходиться в діапазоні ASCII Контрольних символів , і тому не має (або не повинен зазвичай) візуального зображення.

Vim та деякі інші редактори відображають їх, щоб ви могли їх редагувати. Як ви помітили, cat -vвідображається і його. Сторінка man показує, що -vце коротка форма --show-nonprinting, яка змушує її замінити символи, що не надруковуються, на друковане зображення, яке не є оригінальним вмістом файлу і, отже, може спричинити проблеми, якщо вихід насправді в іншій програмі .

Представлення, яке ви бачите, вже натякає на те, що це контрольний символ: символ, який є попередньо символом a, ^є загальним позначенням для Ctrl+ символу, який є комбінацією клавіш, яка створює цей символ у терміналі. Ctrl+ _дозволить вам ввести роздільник одиниць у vim, наприклад. Але інший редактор або якийсь переглядач графічного інтерфейсу може відобразити шістнадцятковий код, заповнювач або щось зовсім інше.

Оскільки ваш термінал не друкує контрольні символи, він також не копіюється під час вибору тексту (символи пробілів, такі як новий рядок та вкладка, тут є виключенням, які також є контрольними символами). Іншим прикладом контрольних символів у терміналі, які зазвичай ігноруються при копіюванні, є кольорові коди, які є ESCсимволом, за яким іде код для розфарбовування тексту.

Отже, щоб показати символи на своєму терміналі, не існує іншого способу, як використовувати програму, яка замінює роздільник пристроїв деяким символом для друку.


3

Трохи на межі інших (дуже хороших) відповідей, якщо ви хочете змінити лише керуючий символ ^_під час відображення вмісту файлу, ви можете передати його транслітерацією за допомогою trутиліти (і трохи синтаксису, сумісного з bash) :

# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'

Якщо вам потрібно замінити цей контрольний символ на його "розширену" форму, вам знадобиться sed:

# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g

Зверніть увагу на синтаксис $'\cX': цей синтаксис повідомляє вашу (сумісну з bash оболонкою), щоб замінити відповідний символ управління. Дивіться у wikipedia список псевдонімів контрольних символів, використовуючи "позначення карет". Якщо вам не подобається цей синтаксис, ви можете скористатись восьмою $'\037'або шістнадцятковою $'\x1f'нотацією.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.