Ctrl + D для закінчення введення термінальної лінії


21

Якщо я це роблю

$ cat > file.txt

текст Ctrl- DCtrl-D

Запитання 1: Якщо я не натискаю клавішу Enter, навіщо мені натискати Ctrl- Dдвічі?

Якщо я це роблю

$ cat > file.txt

pa bam pshhh Ctrl-Z

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

pa bam pshhh

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

@supercat Програма може продовжувати читати, якщо хоче. У exредакторі, якщо ви вводите control-D як перший символ рядка, редактор показує вам кілька рядків програми, а не вихід. (В exі vi, Control-D - мнемонічне значення для "вниз"). І з багатьма оболонками, якщо ви введете Control-D, але у вас є завдання, що працюють у фоновому режимі, оболонка інформує вас про це, а не про вихід, але якщо ви знову введете Control-D, оболонка вирішить, що ви дійсно хочете вийти з нього все одно і зробить це.
— Марк Плотнік

@MarkPlotnick: Чи є якийсь спосіб, через який ці нульові байтові гикавки можуть бути надіслані через трубу?
— supercat

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