
Если я сделаю
$ cat > file.txt
текст Ctrl- DCtrl-D
Вопрос 1: Если я не нажимаю Enter, почему мне нужно нажимать 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 строкой?
решение1
В 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
.
решение2
Это потому, что Ctrl+ D— это хак.
В глубине души Ctrl+ D(несмотря на то, что его называютeof
характер) на самом деле не означает конец файла: это означает «отправить ожидающий ввод в приложение сейчас». Это на самом деле близко к значению Ctrl+ M( eol
), который отправляет ожидающий ввод плюс новую строку.
Когда вы нажимаете Ctrl+ Dсразу после Ctrl+ M(т.е. в начале строки) или после другого Ctrl+ D, ожидающий ввода пуст. Таким образом, приложение получает 0 байт ввода. Вread
вызов, чтение 0 байтов сигнализирует о конце файла.
При нажатии Ctrl+ Zожидающий ввод отбрасывается. Таким образом, обрабатывается только то, что уже было отправлено в приложение (то есть cat
) путем ввода новой строки или Ctrl+ Dперед нажатием Ctrl+ .Z