Ctrl + D для завершения ввода строки терминала

21

Если я сделаю

$ cat > file.txt

текст Ctrl- DCtrl-D

Вопрос 1: Если я не нажимаю ввод, почему я должен нажать Ctrl- Dдважды?

Если я сделаю

$ cat > file.txt

па бам пшхх Ctrl-Z

[2]+  Stopped         cat > file.txt
$ cat file.txt
$ cat > file.txt

па бам пшхх

Ctrl-Z

[2]+  Stopped         cat > file.txt
$ cat file.txt
pa bam pshhh

Почему второй раз файл с 1 строкой?

туман
источник
2
В этой теме под зонтиком stackexchange сайтов есть ответ, который вы ищете: stackoverflow.com/questions/7369170/… . Надеюсь, это поможет.
Да, хотя и не связанный с питоном, мой вопрос дубликат.
туман
Когда вы набираете ctrl-z, вы действительно получаете только новое приглашение оболочки или также получаете сообщение об catостановке?
Марк Плотник
Я обновлю вопрос
туман

Ответы:

30

В Unix большинство объектов, которые вы можете читать и записывать - обычные файлы, каналы, терминалы, жесткие диски - все они напоминают файлы.

Программа вроде catчитает из своего стандартного ввода вот так:

n = read(0, buffer, 512);

который просит 512 байт. nколичество фактически прочитанных байтов, или -1, если есть ошибка.

Если вы делали это неоднократно с обычным файлом, вы получите кучу 512-байтовых чтений, затем несколько более короткое чтение в конце файла, затем 0, если вы попытались прочитать после конца файла. Итак, catбудет работать до тех пор, пока не nстанет <= 0.

Чтение из терминала немного отличается. После ввода строки, оканчивающейся Enterклавишей, readвозвращается только эта строка.

Есть несколько специальных символов, которые вы можете напечатать. Один есть Ctrl-D. Когда вы набираете это, операционная система отправляет всю введенную вами текущую строку (но не Ctrl-Dсаму) в программу, выполняющую чтение. И вот случайная вещь: если Ctrl-Dэто первый символ в строке, программе отправляется строка длиной 0 - точно так же, как программа увидит, добралась ли она до конца обычного файла. cat не нужно ничего делать иначе , будь то чтение из обычного файла или из терминала.

Еще один особый персонаж Ctrl-Z. Когда вы набираете его в любом месте строки, операционная система отбрасывает все, что вы набрали, до этой точки и отправляет сигнал SIGTSTP в программу, которая обычно останавливает (приостанавливает) его и возвращает управление оболочке.

Так в вашем примере

$ cat > file.txt
pa bam pshhh<Ctrl+Z>
[2]+  Stopped         cat > file.txt

Вы набрали несколько символов, которые были отброшены, а затем catостановлены, ничего не записав в его выходной файл.

$ cat > file.txt
pa bam pshhh
<Ctrl+Z>
[2]+  Stopped         cat > file.txt

Вы набрали одну строку, которая catпрочитала и записала в свой выходной файл, а затем Ctrl-Zостановилась cat.

Марк Плотник
источник
1
это относится только к терминалам канонического режима . И даже в этом случае они могут быть изменены.
mikeserv
@mikeserv Это правда. Здесь я хотел объяснить, что видит ОП. Я также рассмотрел описание терминального режима raw / -icanon, других специальных символов, как их можно настроить, как они различаются в зависимости от ОС и т. Д., Но не хотел делать ответ слишком длинным.
Марк Плотник
Означает ли вышесказанное, что если ввод не проходил cat, то программа, которая считывала данные с клавиатуры и не остановилась с первого раза, когда был readполучен ноль, могла бы продолжаться, и количество требуемых элементов управления D будет определяться количество последовательных нулей, необходимое программе, чтобы решить, было ли это сделано?
суперкат
@supercat Программа может продолжать читать, если захочет. В exредакторе, если вы введете control-D в качестве первого символа строки, редактор покажет вам несколько строк программы вместо выхода. (В exи vi, Control-D является мнемоникой для «вниз»). И во многих оболочках, если вы набираете Control-D, но у вас есть задания, работающие в фоновом режиме, оболочка проинформирует вас об этом, а не о выходе, но если вы введете Control-D снова, оболочка решит, что вы действительно хотите выйти в любом случае и будет делать так.
Марк Плотник
@MarkPlotnick: Есть ли способ, с помощью которого эти нулевые байты могут быть отправлены через канал?
суперкат
19

Это потому, что Ctrl+ Dэто хак.

В глубине души Ctrl+ D(несмотря на то, что он называется eofсимволом ) на самом деле не означает конец файла: он означает «отправить ожидающий ввод приложению сейчас». Это на самом деле близко к значению Ctrl+ M( eol), который отправляет ожидающий ввод плюс символ новой строки.

Когда вы нажимаете Ctrl+ Dсразу после Ctrl+ M(то есть в начале строки) или после другого Ctrl+ D, ожидающий ввод будет пустым. Таким образом, приложение получает 0 байтов ввода. При readвызове чтение 0 байтов означает конец файла.


Когда вы нажимаете Ctrl+ Z, ожидающий ввод сбрасывается. Таким образом обрабатывается только то, что уже было отправлено в приложение (то есть cat) путем ввода новой строки или Ctrl+ Dперед нажатием Ctrl+ Z.

Жиль "ТАК - перестань быть злым"
источник
1
Более подробную информацию о ctrl + D из одного ответа Гилла можно найти здесь .
Рамеш
Как вы сказали, Ctrl-D не означает конец файла. На самом деле это не значит, что Ctrl-D - это EOT (конец текста).
H2ONaCl