Каково поведение `cat | less`?

0

Я попытался выполнить следующую команду:

cat | less

Я знаю, что обе команды требуют чего-то от стандартного ввода. Когда я запустил его, это то, что я ожидал: все мои входные данные отправляются в cat, и я не смогу отправлять команды на меньшее количество (в конце концов, не имея возможности выйти из программы с командой q.).

Это не то, что происходит. На самом деле, он работает правильно, пока количество строк, отправляемых в стандартном вводе, меньше, чем количество строк на экране. Когда число строк, отправленных в стандартном вводе, стало больше, чем количество строк моего утешения, появляется странное поведение. Кажется, что вклад иногда отправляется catиногда less, Например, неважно, письмо q иногда дайте программе выйти.

Почему причина такого поведения, которого я (наивно) не ожидал?

user1833218
источник
Еще одна интересная вещь, если я делаю echo a|less он говорит «конец» в конце, но не с cat | less, даже когда он поражает меньше, с cat | less, когда он поражает меньше, он показывает двоеточие для подсказки. Что, да, я думаю, означает, что есть больше на экране. как ты говоришь. Я думаю, что ответ Давидго о буферизации может объяснить это. Кстати, я замечаю, просто набрав less<ENTER> он не запрашивает стандартный ввод, поэтому интересно, что вы можете добавить к нему эхо / канал.
barlop
@ barlop хороший комментарий, я думаю, это связано с другим вопросом, который у меня есть, почему less afilename будет принимать команды в стандартном вводе, и cat afilenime|less будет делать это тоже (не стандартный ввод less на самом деле стандарт cat?).
user1833218
менее принимает только стандартный ввод после его ввода. Например, введите cat & lt; ENTER & gt; Вы видите, что он пытается прочитать ввод. Но чем меньше, тем страннее. Попробуйте меньше & lt; ENTER & gt; и это не читает ввод. Дайте меньше информации, например файл, а затем, он хочет ввода. Я не совсем уверен, что происходит с меньшими затратами ... мне интересно, как это будет закодировано, если бы я знал, то получил бы это ... Вы видели код, который принимает стандартный ввод при запуске? это позволяет вам передавать к нему по конвейеру, а если вы не передаете его по конвейеру, то запрашивает у вас ... я не уверен, хотя и насчет указания имени файла ... как он вызывает это по сравнению со стандартным вводом
barlop

Ответы:

2

CAT будет принимать входные данные от stdin (хотя, возможно, более разумно предпочитает ввод из файла или канала)

Это означает, что входные данные просто передаются через cat, а затем направляются на меньшее. Таким образом, вы можете увидеть результат меньше.

Ваши путаницы, скорее всего, приходят с буферизацией. CAT буферизует входные данные и будет пакетировать их (или ожидает окончания файла) при отправке его на less для форматирования.

davidgo
источник
2

Я ненавижу себя за то, что говорю это, но

Существует более одного способа cat,

Под этим я подразумеваю стандартный ввод, а затем стандартный ввод. Или есть чтение с клавиатуры (терминала), а затем есть чтение с клавиатуры. Пытаться

less < afilename

Это работает так же, как

less afilename

что значит less должен иметь какой-то способ чтения с клавиатуры кроме чтения из стандартного ввода. Вот еще одна команда, которая работает, даже если вы этого не ожидаете:

less afilename < /dev/null

смотреть на tty команда , Он сообщает имя tty (терминала), подключенного к стандартному входу. Это работает по телефону ttyname функция библиотеки с аргументом 0 (файловый дескриптор стандартного ввода).

less вероятно звонит ttyname(1) получить имя tty (терминала), подключенного к стандартному выходу. Затем он открывает этот tty для чтения и принимает от него команды. Он не читает команды из стандартного ввода; это только для данных.

Так что у нас есть два квази-независимых процесса ( cat а также less ) независимо (одновременно) чтение с клавиатуры (то есть tty / терминал) на двух независимых файловых дескрипторах. Это запутанная ситуация, и это что-то вроде «состояния гонки». Я нахожу это несколько аналогичным операции пинбол , в котором есть много дорожек или дорожек, по которым может пройти мяч - и это всегда занимает один ; это никогда не может занять больше, чем один. Так же, когда несколько процессов читают с одного терминала одновременно, каждая набранная строка (если терминал находится в режиме строки) или каждый набранный символ (если терминал находится в символьном режиме) идет ровно на один процесс. И выбор произвольный, мало чем отличающийся от действия пинбола. Он не полностью «случайный», не более чем случайное планирование процессов; но это по сути непредсказуемо.

Итак, вот что происходит:

  • cat читает со своего стандартного входа, который по умолчанию является терминалом, и пишет в свой стандартный вывод, который является каналом для less,
  • В какой-то момент, less звонки ttyname(1), получает имя терминала, на котором он включен, и открывает его для чтения.
  • less читает данные, заполненные экраном (то есть 24 строки или что-то еще) со своего стандартного ввода (труба) и записывает его на стандартный вывод (терминал).
  • Затем, less выдает : подскажите, переводит терминал в символьный режим, и начинает читать из терминала ( не со стандартного ввода).
  • Итак, теперь у нас есть два процесса ( cat а также less ) чтение с терминала одновременно, и феномен пинбола включается - персонажи (и / или линии) что вы печатаете, перейдите либо cat или же lessполу-случайно. Если это идет к catзаписывается в трубу и less трактует это как данные. Если это идет к less, это интерпретируется как less команда.

Это не имеет никакого отношения к буферизации.

Scott
источник
1
Хороший ответ, но less просто открывается /dev/tty: "/ dev / tty: в каждом процессе - синоним для управляющего терминала, связанного с группой процессов этого процесса, если таковой имеется. Это полезно для программ или процедур оболочки, которые хотят быть уверены, что пишут сообщения или читают данные из Терминал, независимо от того, как был перенаправлен вывод. Он также может использоваться для приложений, которые требуют имя файла для вывода, когда требуется печатный вывод, и утомительно выяснять, какой терминал используется в настоящее время ». (Posix: pubs.opengroup.org/onlinepubs/9699919799/basedefs/... )
rici
D'о! Ты прав; Я упустил очевидное.
Scott