1

Можно предположить, что, поскольку каждая вкладка перемещается на 8 столбцов по умолчанию, консоль из 80 столбцов будет иметь ровно 10 позиций табуляции. Это может быть опровергнуто:

$ printf "1\t2\t3\t4\t5\t6\t7\t8\t9\t0\ta"

Можно ожидать, что результат будет в 2 строки, потому что есть 10 табуляций, занимающих место всех 80 столбцов, плюс один символ, который должен быть перенесен на следующую строку. Но команда выдает одну строку вывода в xterm, gnome-terminal и rxvt.

Случилось так, что последний табулатур магическим образом занимает на один символ меньше места.

Между тем, expand(1) утверждает, что пространство табуляции равно 8, таким образом

$ printf "1\t2\t3\t4\t5\t6\t7\t8\t9\t0\ta" | expand

будет магически производить 2 строки на консоли с 80 колонками.

Кажется, стандарт какой-то. Но я просто не могу найти источник по поиску.

Протестировано только в Linux, но я боюсь, что это разделяют все Unix.

1 ответ1

12

На 80-колоночной консоли всего 9 табов.

Давайте сначала расширим комментарий. Вы на самом деле не тестировали никаких консолей. Это все программы эмулятора терминала с графическим интерфейсом. К счастью, настоящие консоли (по крайней мере на Linux и FreeBSD) также демонстрируют такое поведение.

Но это не поведение, которое вы утверждаете. Это не демонстрирует 11 вкладок. Это демонстрирует 9.

Чтобы правильно понять табуляторы, вам нужно выбросить «Они всегда расширяются до N пробелов». идея. Если у вас есть доступ к механической пишущей машинке с помощью вкладок, посмотрите и посмотрите, как она работает (вкладки устанавливаются с помощью выступов на каретке). Вкладки в терминалах в мире Unix и Linux работают таким образом.

(Можно настроить дисциплину строк, чтобы вводить мягкие вкладки, заменяя символы табуляции в выходном потоке символами пробела, прежде чем они когда-либо достигнут терминала. Здесь мы обсуждаем жесткие вкладки, выполняемые самим терминалом, а не линейной дисциплиной. С жесткими вкладками на терминал отправляется символ TAB FIDE FIDE . С мягкими вкладками, наоборот, описанное вами поведение не происходит в первую очередь. Попробуй установить stty tab3 и посмотри.)

При инициализации в терминале вообще не установлено табуляции. getty или команда reset или что-то похожее (в зависимости от системы) выводит последовательность пробелов и escape-последовательностей, которые устанавливают табуляции в определенных столбцах. Иногда столбцы и даже escape-последовательности жестко зашиты. Чаще всего, однако, команда ищет информацию в базе данных termcap/terminfo. Возможность terminfo, дающая escape-последовательность для очистки всех вкладок, является tbc ; возможность hts дает управляющую последовательность для установки вкладки в текущем столбце; и возможность it определяет количество столбцов между табуляциями по умолчанию. Для termcap эквивалентными возможностями являются it , ct и st .

Команда получает размер терминала (из ядра, с помощью системного вызова или из другой части записи terminfo/termcap), просматривает количество столбцов и многократно выводит it пробелы, за которыми следует последовательность st для столько столбцов, сколько может, наконец, вывести возврат каретки, чтобы вернуться к столбцу № 0. Именно так можно установить набор табуляторов на многих механических пишущих машинках: несколько раз пробелить до следующей табуляции, нажать рычаг "установить табуляцию", чтобы вытолкнуть штифт, повторить до правого поля, сдвинуть каретку назад влево ,

Для 80-колонки с шириной терминала, с it дается как 8 , как это обычно бывает, команда делает это девять раз, установив символ табуляции в столбцах 8, 16, 24, 32, 40, 48, 56, 64 и 72.

В столбце 0 нет табуляции (за исключением ошибки в программе). Это ваша первая ошибка подсчета. Там также нет табуляции в столбце 80, ваша вторая ошибка подсчета. "Почему", спросите вы, «это?"Во - первых, это происходит потому , что это не возможно , чтобы быть в колонке 80 , чтобы установить TabStop. Курсор перемещается из столбца 0 в столбец 79 на терминале с 80 столбцами.

Во-вторых, нужно подумать о поведении персонажа TAB . Это не, вопреки распространенному мнению, расширить до достаточно пространства , чтобы перейти к следующему кратному 8 столбцов. Помните, терминалы Unix и Linux работают как механические пишущие машинки. В мире механических пишущих машинок клавиша табуляции перемещает каретку до тех пор, пока она не будет остановлена штифтом табло или правым полем. (Некоторые умные засорения могут упомянуть выпуск маржи на этом этапе. Это то, что есть у механических пишущих машинок, чего нет у терминалов Unix и Linux по понятным причинам.)

Символ TAB на терминалах Unix и Linux на самом деле работает одинаково. В ответ на это терминал испускает пробелы, пока не будет достигнут следующий набор табуляции или самый правый столбец. И вот что здесь происходит. Когда курсор находится в столбце 79, вы можете написать столько символов TAB сколько захотите, и ничего не произойдет. Там нет табуляции за крайним правым столбцом.

Система termcap/terminfo позволяет устанавливать жесткие вкладки по желанию. Но все программы, которые вы тестировали, предоставляют эмулятор терминала типа "xterm". (Экранирующие последовательности, которые он понимает, приведены в записи / записях xterm в базе данных termcap/terminfo.) То же самое и в настоящее время делает эмулятор терминала в виртуальной консоли FreeBSD. Эмулятор терминала в виртуальной консоли Linux на самом деле представляет собой немного другой тип терминала, обозначаемый как linux . (Раньше так было и с виртуальной консолью FreeBSD, которая имела тип cons25 . FreeBSD изменила свой эмулятор терминала ядра, чтобы он стал совместимым с xterm в версии 9.0, как часть проекта, чтобы получить поддержку UTF-8 на виртуальных консолях.) Все эти xterm-подобные программы и эмулятор терминала ядра Linux имеют полностью настраиваемый механизм жестких вкладок.

(Для тех, кто любит читать исходники: посмотрите на функции TabNext() и TabToNextStop() в tabs.c в исходном коде xterm .)

Вы можете попробовать это для себя. Запустите эти команды:

tbc=$(tput tbc) hts=$(tput hts)
printf '%s\r%s\r\n' "${tbc}" "a${hts}aaa${hts}aaaaaaa${hts}aaaaaaaaaaaaa${hts}aaaaaaaaaaaaaaaaaa${hts}"

Затем запустите вашу команду снова. Ровно пять вкладок были установлены. Подсчитайте ${hts} в команде, или посмотреть на линию символов. Помимо пятого, символ a заставляет эту метафорическую каретку пишущей машинки проделывать весь оставшийся путь до правого поля.

Следующий (печатный, не TAB) символ вызывает автоматический возврат каретки к левому полю и перевод строки на следующую строку. В терминологии termcap/terminfo тип терминала xterm имеет автоматические поля. Теоретически, Unix и Linux могут работать с терминалами, которые не имеют автоматических полей. Ваша команда printf застрянет в столбце 79, независимо от того, сколько вы выводите, пока вы не напишите возврат каретки. На практике такое устройство ошеломило бы умы большинства людей в наши дни.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .