J'ai donc beaucoup de données SANS NOUVELLES LIGNES dans le presse-papiers (c'est un gros fichier SVG sur une seule ligne). je suis allé
$ cat >file.svg
a ensuite essayé de coller (dans Gnome Terminal), mais seuls les 4 premiers caractères de 4 Ko ont été acceptés.
Je suppose que c'est une fonction / limitation de ligne de lecture.
Existe-t-il un moyen de lire à partir de STDIN qui permettrait d'éviter ce problème?
MODIFIER
Cas de test: créez un fichier de démonstration. Celui-ci aura ~ 4k "=" symboles suivis de "foo bar".
{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Copiez cela dans votre presse-papiers
xclip test.in
(si vous voulez cliquer avec le bouton du milieu pour insérer) ou
xclip -selection clipboard test.in
(si vous souhaitez utiliser Ctrl-Maj-Insert pour le coller)
Ensuite cat >test.out
, collez (quelle que soit la façon). Appuyez sur Ctrl-D pour terminer le flux. cat test.out
- voyez-vous "foo bar"?
Sur ma configuration (Ubuntu 12.04, Gnome Terminal, zsh) lorsque je colle, je ne vois que le =
et je ne le vois pas foo bar
. Pareil quand j'inspecte test.out
.
Réponses:
Si je comprends bien la source, sous Linux, le nombre maximum de caractères pouvant être lus en une seule fois sur un terminal est déterminé par
N_TTY_BUF_SIZE
dans la source du noyau. La valeur est 4096.Il s'agit d'une limitation de l'interface du terminal, en particulier du mode canonique («cuit») qui fournit un éditeur de ligne extrêmement grossier (retour arrière, entrée, Ctrl+ Dau début d'une ligne pour la fin du fichier). Cela se passe entièrement en dehors du processus de lecture.
Vous pouvez basculer le terminal en mode brut, ce qui désactive le traitement en ligne. Il désactive également Ctrl+ Det d'autres subtilités, mettant un fardeau supplémentaire sur votre programme.
Il s'agit d'une ancienne limitation Unix qui n'a jamais été corrigée car il y a peu de motivation. Les humains n'entrent pas dans de si longues files d'attente. Si vous alimentiez l'entrée d'un programme, vous redirigeriez l'entrée de votre programme à partir d'un fichier ou d'un canal.
Par exemple, pour utiliser le contenu du presse-papiers X, du tuyau depuis
xsel
ouxclip
. Dans ton cas:Supprimez
-b
ou-selection clipboard
pour utiliser la sélection X (celle qui est définie en surlignant avec la souris) plutôt que le presse-papiers.Sous OSX, utilisez
pbpaste
pour coller le contenu du presse-papiers (etpbcopy
pour le définir).Vous pouvez accéder au presse-papiers X via SSH si vous activez le transfert X11
ssh -X
(ce que certains serveurs peuvent interdire). Si vous ne pouvez utiliserssh
sans transfert X11, vous pouvez utiliserscp
,sftp
ousshfs
pour copier un fichier.Si le collage est la seule solution parce que vous ne pouvez pas transférer le presse-papiers ou que vous ne collez pas, mais p. Base64 est bien adapté à cela: il transforme des données arbitraires en caractères imprimables et ignore les espaces lors du décodage. Cette approche présente l'avantage supplémentaire de prendre en charge des données arbitraires en entrée, même des caractères de contrôle que le terminal interpréterait lors du collage. Dans votre cas, vous pouvez encoder le contenu:
puis le décoder:
la source
xsel
avec> 4k octets: github.com/kfish/xsel/issues/14La limite que vous utilisez en est la taille maximale d'une ligne en mode d'entrée canonique ,
MAX_CANON
.En mode d'entrée canonique, le pilote tty fournit des services d'édition de ligne de base afin que le programme de l'espace utilisateur n'en ait pas besoin. Il n'a pas autant de fonctionnalités que readline, mais il reconnaît quelques caractères spéciaux configurables comme l'effacement (généralement Backspace ou Delete) et kill (généralement Ctrl-U).
Plus important encore pour votre question, les tampons en mode canonique sont entrés jusqu'à ce que le caractère de fin de ligne soit visible. Parce que le tampon est dans le pilote tty, dans la mémoire du noyau, il n'est pas très grand.
Vous pouvez désactiver le mode canonique avec
stty cbreak
oustty -icanon
, puis faire votre collage. Cela présente l'inconvénient majeur de ne pas pouvoir envoyer un EOF avec Ctrl-D. C'est une autre des choses dont le mode canonique est responsable. Vous pourrez toujours terminer lecat
avec Ctrl-C car les caractères générant le signal sont contrôlés par un drapeau séparé (stty raw
oustty -isig
).Le mystère pour moi est pourquoi, puisque vous avez déjà démontré que vous savez
xclip
, vous ne vous contentez pas d' utiliser auxclip -o > file
lieu decat
la source
Si tu fais:
Et puis exécutez la démo suggérée dans votre EDIT , vous verrez foo bar dans l'impression de test.out . La discipline de ligne du terminal videra sa sortie vers son lecteur pendant qu'il lit chaque caractère EOL spécial dans votre entrée.
Un terminal en mode canonique Linux - tel qu'il peut être configuré avec
stty icanon
ou probablement justestty sane
- gère les caractères d'entrée spéciaux suivants ...^D
^U
^H
(ou éventuellement@
ou^?
sur certains systèmes)Lorsque iexten est également défini - comme
stty icanon iexten
ou, encore une fois, probablement justestty sane
, un terminal Linux canonique gérera également ...^W
^R
^V
Ces caractères sont gérés en les supprimant du flux d'entrée - à l'exception de eol et eol2 , c'est-à-dire - et en exécutant la fonction spéciale associée avant de transmettre le flux traité au lecteur - qui est généralement votre shell, mais pourrait être le groupe de processus de premier plan quel qu'il soit. .
D'autres caractères d'entrée spéciaux qui sont traités de la même manière mais qui peuvent être configurés indépendamment de tout paramètre icanon incluent le jeu isig - défini comme
stty isig
et probablement également inclus dans une configuration saine :^\
^Z
kill -CONT "$!"
ou simplementfg
dans un shell contrôlé par le travail (set -m
) .^C
Et l' ensemble ixon - configuré comme
stty ixon
et également généralement inclus dans une configuration saine :^S
^Q
Les caractères spéciaux gérés sur d'autres systèmes non Linux peuvent inclure ...
^O
Et peut-être ...
^@
(sens\0
ouNUL
)shl
shell-couches sur certains systèmes.shl
dont multiplexe ptys et est donc compatible avec le contrôle des tâches plutôt que le comportement dépendant de swtch de l'implémentation d' origine peut être librement disponible dans laheirloom-toolchest
suite d'outils.Pour une image plus claire de comment et pourquoi (et peut-être pourquoi pas) ces fonctions d'entrée sont gérées, consultez
man 3 termios
.Toutes les fonctions ci-dessus peuvent être attribuées (ou réaffectées) - le cas échéant - comme
stty
function assigned-key
. Pour désactiver une fonction unique, faites . Alternativement, comme diverses tentatives avec des affectations pour l'une des fonctions d'édition de ligne susmentionnées avec toutes les implémentations de GNU, AST ou de l'héritage semblent l'indiquer, vous pouvez également, comme l' affectation NUL pour n'importe quelle fonction semble équivaloir à la définir comme non affectée sur mon linux système.stty
function
^-
stty
stty
function
^@
Vous voyez probablement un écho de ces caractères lorsque vous les tapez (comme cela peut probablement être configuré avec [-] ctlecho ) , mais ce n'est qu'un marqueur pour vous montrer où vous en êtes - le programme recevant votre entrée n'a aucune idée que vous les a tapés (sauf eol [2] , c'est-à-dire) et ne reçoit qu'une copie de votre saisie à laquelle la discipline de ligne a appliqué leurs effets.
Une conséquence de la gestion par le terminal des diverses fonctions d'édition de ligne est qu'il doit dans une certaine mesure mettre en mémoire tampon l'entrée afin d'agir sur les fonctions que vous lui indiquez qu'il devrait - et donc il ne peut pas y avoir une fourniture illimitée d'entrée qui vous pourriez à tout moment tuer . Le tampon de ligne est plus précisément le tampon de mise à mort .
Si vous définissez les caractères eol ou eol2 sur un délimiteur qui se produit en entrée - même si ni un saut de ligne ni un caractère de retour, par exemple - alors vous ne pourrez tuer que jusqu'au dernier point et votre tampon de mise à mort s'étendra aussi loin que possible jusqu'à ce que la prochaine - ou une nouvelle ligne (ou retourne si icrnl est défini et igncr ne l'est pas) - se produit en entrée.
la source
cat
acceptera n'importe quel nombre de caractères, comme vous pouvez en témoigner par exemplecat /dev/random > test.bin
(ne le faites pas à moins de savoir comment l'arrêter :). J'ai essayé de copier et coller un gros fichier danscat > test.txt
. Toutes les lignes se sont retrouvées dans le fichier, que j'aie annulé avec Ctrl- cou Ctrl- d, mais dans le premier cas, toutes les lignes n'ont pas été imprimées sur le terminal . Je pense que c'est parce quecat
tampon son impression, attendant un tampon complet de texte ou une entrée directe du terminal avant chaque impression.Sur mon système, je pense que la taille du tampon est de 4096 (2 ^ 12) octets: créez un fichier de 4095 octets en utilisant
(printf '1234567890%.0s' {1..409} && printf 12345) > test.in
, chargez-le dans le tampon de copie en utilisantxclip test.in
, démarrezcat > test.out
, collez en utilisant Shift- Insertet terminez le flux en appuyant sur Ctrl- d. Ajoutez maintenant un octet à l'aide deprintf '6' >> test.in
, et le flux est imprimé deux fois : une fois dans lacat
sortie (tous les 4096 octets) et les 4095 derniers octets à nouveau sur le shell après la fin.la source
Une solution consiste à le coller dans un éditeur qui prend en charge les longues lignes, par exemple vim.
Si vous utilisez vim, entrez d'abord en
:paste
↵mode icollage avec avant de passer en mode insertion avec et de coller le texte.la source