Ctrl + D pour terminer l'entrée de la ligne terminale

21

Si je fais

$ cat > file.txt

texte Ctrl- DCtrl-D

Question 1: Si je n'appuie pas sur Entrée, pourquoi dois-je appuyer Ctrl- Ddeux fois?

Si je fais

$ 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

Pourquoi est la deuxième fois le fichier avec 1 ligne?

brouillard
la source
2
Ce fil sous le parapluie des sites stackexchange a la réponse que vous regardez: stackoverflow.com/questions/7369170/… . J'espère que ça aide.
Oui, même si ce n'est pas lié à Python, ma question est en double.
brouillard
Lorsque vous tapez ctrl-z, obtenez-vous vraiment juste une nouvelle invite de shell, ou recevez-vous également un message d' catarrêt?
Mark Plotnick
Je mettrai à jour la question
brume

Réponses:

30

Sous Unix, la plupart des objets que vous pouvez lire et écrire - fichiers ordinaires, canaux, terminaux, lecteurs de disque bruts - sont tous conçus pour ressembler à des fichiers.

Un programme comme catlit à partir de son entrée standard comme ceci:

n = read(0, buffer, 512);

qui demande 512 octets. nest le nombre d'octets réellement lus, ou -1 s'il y a une erreur.

Si vous faisiez cela à plusieurs reprises avec un fichier ordinaire, vous obtiendrez un tas de lectures de 512 octets, puis une lecture un peu plus courte à la fin du fichier, puis 0 si vous essayez de lire après la fin du fichier. Donc, cats'exécutera jusqu'à ce que n<= 0.

La lecture à partir d'un terminal est légèrement différente. Après avoir tapé une ligne, terminée par la Enterclé, readrenvoie uniquement cette ligne.

Vous pouvez saisir quelques caractères spéciaux. L'un est Ctrl-D. Lorsque vous saisissez cela, le système d'exploitation envoie toute la ligne actuelle que vous avez tapée (mais pas la ligne Ctrl-Delle - même) au programme effectuant la lecture. Et voici la chose fortuite: si Ctrl-Dest le premier caractère sur la ligne, le programme reçoit une ligne de longueur 0 - tout comme le programme verrait s'il arrive juste à la fin d'un fichier ordinaire. cat n'a pas besoin de faire quoi que ce soit différemment , que ce soit la lecture d'un fichier ordinaire ou d'un terminal.

Un autre caractère spécial est Ctrl-Z. Lorsque vous le tapez, n'importe où dans une ligne, le système d'exploitation rejette tout ce que vous avez tapé jusqu'à ce point et envoie un signal SIGTSTP au programme, qui normalement l'arrête (le met en pause) et rend le contrôle au shell.

Donc, dans votre exemple

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

vous avez tapé certains caractères qui ont été supprimés, puis avez catété arrêté sans avoir rien écrit dans son fichier de sortie.

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

vous avez tapé une ligne, qui a catlu et écrit dans son fichier de sortie, puis Ctrl-Zarrêté cat.

Mark Plotnick
la source
1
ces choses ne sont valables que pour les terminaux en mode canonique . Et même dans ce cas, ils peuvent être modifiés.
mikeserv
@mikeserv C'est vrai. Ici, je voulais expliquer ce que voyait le PO. J'ai envisagé de décrire également le mode terminal raw / -icanon, d'autres caractères spéciaux, comment ils peuvent être personnalisés, comment ils diffèrent selon le système d'exploitation, etc., mais je ne voulais pas rendre la réponse trop longue.
Mark Plotnick
Est-ce que ce qui précède implique que si l'entrée ne passait pas cat, qu'un programme qui lirait les données du clavier et ne s'arrêterait pas la première fois readproduirait un zéro pourrait continuer, et le nombre de control-D requis serait déterminé par le nombre de zéros consécutifs nécessaires au programme pour décider qu'il a été fait?
supercat
@supercat Un programme peut continuer à lire s'il le souhaite. Dans l' exéditeur, si vous tapez un contrôle-D comme premier caractère d'une ligne, l'éditeur vous montre quelques lignes du programme plutôt que de quitter. (Dans exet vi, Control-D est un mnémonique pour "down"). Et avec de nombreux shells, si vous tapez Control-D mais que des tâches s'exécutent en arrière-plan, le shell vous en informera plutôt que de quitter, mais si vous tapez à nouveau Control-D, le shell décide que vous voulez vraiment quitter de toute façon et le fera.
Mark Plotnick
@MarkPlotnick: Existe-t-il un moyen d'envoyer ces hoquets à zéro octet via le canal?
supercat
19

C'est parce que Ctrl+ Dest un hack.

Au fond, Ctrl+ D(bien qu'on l'appelle le eofpersonnage ) ne signifie pas réellement la fin du fichier: cela signifie «envoyer l'entrée en attente à l'application maintenant». C'est en fait proche de la signification de Ctrl+ M( eol), qui envoie l'entrée en attente plus une nouvelle ligne.

Lorsque vous appuyez sur Ctrl+ Dimmédiatement après un Ctrl+ M(c'est-à-dire au début d'une ligne) ou après un autre Ctrl+ D, l'entrée en attente est vide. Ainsi, l'application reçoit 0 octet d'entrée. Lors d'un readappel, la lecture de 0 octet signale la fin du fichier.


Lorsque vous appuyez sur Ctrl+ Z, l'entrée en attente est supprimée. Ainsi, seul ce qui avait déjà été envoyé à l'application (qui est cat) en entrant une nouvelle ligne ou Ctrl+ Davant d'appuyer sur Ctrl+ Zest traité.

Gilles 'SO- arrête d'être méchant'
la source
1
Plus d'informations concernant ctrl + D dans l'une des réponses de Gille peuvent être trouvées ici .
Ramesh
Comme vous l'avez dit, Ctrl-D ne signifie pas fin de fichier. En fait, cela ne signifie pas que c'est parce que Ctrl-D est EOT (fin de texte).
H2ONaCl