Ctrl + D do zakończenia linii wejściowej terminala

21

Jeśli zrobię

$ cat > file.txt

tekst Ctrl- DCtrl-D

Pytanie 1: Jeśli nie naciskam Enter, dlaczego muszę naciskać Ctrl- Ddwa razy?

Jeśli zrobię

$ 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

Dlaczego po raz drugi plik ma 1 linię?

zamglenie
źródło
2
Wątek pod parasolem witryn stosu wymiany zawiera odpowiedź, na którą patrzysz: stackoverflow.com/questions/7369170/… . Mam nadzieję, że to pomoże.
Tak, nawet jeśli nie jest związane z pythonem, moje pytanie jest duplikatem.
mgła
Kiedy wpiszesz ctrl-z, czy naprawdę pojawia się tylko nowy monit powłoki, czy też pojawia się komunikat o catzatrzymaniu?
Mark Plotnick,
Zaktualizuję pytanie
zamglę

Odpowiedzi:

30

W Uniksie większość obiektów, które można odczytywać i zapisywać - zwykłe pliki, potoki, terminale, napędy dyskowe - wszystko to przypomina pliki.

Program taki catczyta ze swojego standardowego wejścia, takiego jak ten:

n = read(0, buffer, 512);

który prosi o 512 bajtów. njest liczbą faktycznie odczytanych bajtów lub -1, jeśli wystąpił błąd.

Jeśli robiłeś to wielokrotnie ze zwykłym plikiem, dostaniesz wiązkę 512-bajtowych odczytów, a następnie nieco krótszy odczyt na końcu pliku, a następnie 0, jeśli spróbujesz odczytać poza końcem pliku. Więc catbędzie działał, dopóki nie nbędzie <= 0.

Odczyt z terminala jest nieco inny. Po wpisaniu wiersza zakończonego Enterklawiszem readzwraca tylko ten wiersz.

Możesz wpisać kilka znaków specjalnych. Jednym jest Ctrl-D. Po wpisaniu tego system operacyjny wysyła cały bieżący wiersz, który wpisałeś (ale nie Ctrl-Dsam) do programu wykonującego odczyt. A oto przypadkowa rzecz: jeśli Ctrl-Djest to pierwszy znak w linii, program wysyła linię o długości 0 - tak jak program zobaczyłby, gdyby dotarł do końca zwykłego pliku. cat nie musi robić nic innego , niezależnie od tego, czy odczytuje ze zwykłego pliku czy terminala.

Inną postacią specjalną jest Ctrl-Z. Po wpisaniu w dowolnym miejscu linii system operacyjny odrzuca wszystko, co napisałeś do tego momentu, i wysyła sygnał SIGTSTP do programu, który normalnie zatrzymuje go (zatrzymuje) i zwraca kontrolę do powłoki.

Więc w twoim przykładzie

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

wpisałeś kilka znaków, które zostały odrzucone, a następnie catzostał zatrzymany bez zapisania czegokolwiek w pliku wyjściowym.

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

wpisałeś jedną linię, która catczytała i zapisywała swój plik wyjściowy, a następnie Ctrl-Zzatrzymała się cat.

Mark Plotnick
źródło
1
te rzeczy dotyczą tylko terminali w trybie kanonicznym . I nawet w takim przypadku można je zmienić.
mikeserv
@mikeserv To prawda. Tutaj chciałem wyjaśnić, co widział OP. Zastanawiałem się nad opisaniem trybu terminala raw / -icanon, innymi znakami specjalnymi, jak można je dostosować, czym różnią się w zależności od systemu operacyjnego itp., Ale nie chciałem, aby odpowiedź była zbyt długa.
Mark Plotnick,
Czy powyższe implikuje, że gdyby wejście nie przechodziło cat, program, który czytał dane z klawiatury i nie zatrzymywał się po raz pierwszy, readdawał zero, mógł kontynuować, a liczba wymaganych D-Control byłaby określona przez liczba kolejnych zer zerowych wymaganych przez program do podjęcia decyzji?
supercat
@ superuper Program może czytać dalej, jeśli chce. W exedytorze, jeśli wpiszesz control-D jako pierwszy znak linii, edytor pokaże ci kilka linii programu zamiast wychodzenia. (W exi viControl-D to mnemonik dla „down”). W przypadku wielu powłok, jeśli wpiszesz Control-D, ale zadania działają w tle, powłoka poinformuje Cię o tym, a nie wyjdzie, ale jeśli ponownie wpiszesz Control-D, powłoka zdecyduje, że naprawdę chcesz wyjść i tak zrobię.
Mark Plotnick
@MarkPlotnick: Czy jest jakiś sposób, za pomocą którego czkawki zerowe mogą być wysyłane za pomocą potoku?
supercat
19

To dlatego, że Ctrl+ Dto hack.

W głębi duszy Ctrl+ D(pomimo tego, że jest nazywany eofpostacią ) tak naprawdę nie oznacza końca pliku: oznacza „wyślij oczekujące dane wejściowe do aplikacji teraz”. Jest to w rzeczywistości bliskie znaczeniu Ctrl+ M( eol), który wysyła oczekujące dane wejściowe plus nowy wiersz.

Gdy naciśniesz Ctrl+ Dnatychmiast po znaku Ctrl+ M(tj. Na początku wiersza) lub po innym znaku Ctrl+ D, oczekiwane dane wejściowe są puste. W ten sposób aplikacja otrzymuje 0 bajtów danych wejściowych. W readwywołaniu odczyt 0 bajtów sygnalizuje koniec pliku.


Po naciśnięciu Ctrl+ Zoczekujące dane wejściowe są odrzucane. W ten sposób przetwarzane jest tylko to, co zostało już przesłane do aplikacji (czyli jest cat) przez wprowadzenie nowej linii lub Ctrl+ Dprzed naciśnięciem Ctrl+ Z.

Gilles „SO- przestań być zły”
źródło
1
Więcej informacji na temat ctrl + D z jednej z odpowiedzi Gille można znaleźć tutaj .
Ramesh
Jak powiedziałeś, Ctrl-D nie oznacza końca pliku. W rzeczywistości nie oznacza to, że Ctrl-D to EOT (koniec tekstu).
H2ONaCl,