Ich habe also viele Daten OHNE NEUE ZEILEN in der Zwischenablage (es ist eine große SVG-Datei in einer Zeile). ich ging
$ cat >file.svg
Dann wurde versucht einzufügen (in Gnome Terminal), aber nur die ersten 4kB Zeichen wurden akzeptiert.
Ich gehe davon aus, dass dies eine Readline-Funktion / Einschränkung ist.
Gibt es eine Möglichkeit, aus STDIN zu lesen, um dieses Problem zu vermeiden?
BEARBEITEN
Testfall: Erstellen Sie eine Demo-Datei. Dieser hat ~ 4k "=" Symbole, gefolgt von "foo bar".
{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Kopieren Sie das in Ihre Zwischenablage
xclip test.in
(Wenn Sie zum Einfügen mit der mittleren Maustaste klicken möchten) oder
xclip -selection clipboard test.in
(wenn Sie Strg-Umschalt-Einfügen verwenden möchten, um es einzufügen)
Dann cat >test.out
einfügen (welcher Art auch immer). Drücken Sie Strg-D, um den Stream zu beenden. cat test.out
- siehst du "foo bar"?
In meinem Setup (Ubuntu 12.04, Gnome Terminal, zsh) sehe ich beim Einfügen nur das =
und nicht das foo bar
. Das gleiche gilt, wenn ich mich umsehe test.out
.
Antworten:
Wenn ich die Quelle richtig verstehe, wird unter Linux die maximale Anzahl von Zeichen, die auf einem Terminal auf einmal gelesen werden können, durch
N_TTY_BUF_SIZE
die Kernelquelle bestimmt. Der Wert ist 4096.Dies ist eine Einschränkung der Terminalschnittstelle, insbesondere des kanonischen ("gekochten") Modus, der einen äußerst groben Zeileneditor bietet (Rücktaste, Eingabe, Ctrl+ Dam Anfang einer Zeile für das Dateiende). Es geschieht völlig außerhalb des Prozesses, der liest.
Sie können das Terminal in den Raw-Modus schalten, wodurch die Leitungsverarbeitung deaktiviert wird. Es deaktiviert auch Ctrl+ Dund andere Feinheiten, was Ihr Programm zusätzlich belastet.
Dies ist eine alte Unix-Einschränkung, die nie behoben wurde, weil es wenig Motivation gibt. Menschen treten nicht in so lange Schlangen ein. Wenn Sie Eingaben von einem Programm einspeisen, leiten Sie die Eingaben Ihres Programms von einer Datei oder einer Pipe um.
Um beispielsweise den Inhalt der X-Zwischenablage zu verwenden, leiten Sie von
xsel
oderxclip
. In Ihrem Fall:Entfernen Sie
-b
oder-selection clipboard
, um die Auswahl X (die durch Markieren mit der Maus festgelegt wird) anstelle der Zwischenablage zu verwenden.Verwenden Sie unter OSX, um
pbpaste
den Inhalt der Zwischenablage einzufügen (undpbcopy
festzulegen).Sie können über SSH auf die X-Zwischenablage zugreifen, wenn Sie die X11-Weiterleitung aktivieren
ssh -X
(was einige Server möglicherweise verbieten). Wenn Sie nur verwenden können ,ssh
ohne X11 - Weiterleitung, können Sie verwendenscp
,sftp
odersshfs
eine Datei zu kopieren.Wenn das Einfügen die einzige Lösung ist, weil Sie die Zwischenablage nicht weiterleiten können oder nicht einfügen, sondern beispielsweise die Eingabe in eine virtuelle Maschine vortäuschen, können Sie die Daten auch in Zeilenumbrüche codieren. Base64 ist dafür gut geeignet: Es wandelt beliebige Daten in druckbare Zeichen um und ignoriert Leerzeichen beim Dekodieren. Dieser Ansatz hat den zusätzlichen Vorteil, dass er beliebige Daten in der Eingabe unterstützt, sogar Steuerzeichen, die das Terminal beim Einfügen interpretieren würde. In Ihrem Fall können Sie den Inhalt kodieren:
dann dekodiere es:
quelle
xsel
4 KByteDie Grenzen Sie in läufst ist die maximale Größe einer Zeile im kanonischen Eingabemodus ,
MAX_CANON
.Im kanonischen Eingabemodus stellt der tty-Treiber grundlegende Zeilenbearbeitungsdienste bereit, sodass das Userspace-Programm dies nicht muss. Es hat nicht annähernd so viele Funktionen wie readline, erkennt jedoch einige konfigurierbare Sonderzeichen wie Erase (normalerweise Backspace oder Delete) und Kill (normalerweise Ctrl-U).
Am wichtigsten für Ihre Frage ist, dass der kanonische Modus die Eingabe puffert, bis das Zeilenendezeichen angezeigt wird. Da sich der Puffer im tty-Treiber im Kernel-Speicher befindet, ist er nicht sehr groß.
Sie können den kanonischen Modus mit
stty cbreak
oder ausschaltenstty -icanon
und dann einfügen. Dies hat den entscheidenden Nachteil, dass Sie mit Strg-D kein EOF senden können. Das ist eine andere Sache, für die der kanonische Modus verantwortlich ist. Sie können dascat
mit Strg-C beenden, da die signalerzeugenden Zeichen durch ein separates Flag (stty raw
oderstty -isig
) gesteuert werden .Das Rätsel für mich ist, warum Sie, da Sie bereits bewiesen haben, dass Sie davon wissen
xclip
, nicht nur das verwenden,xclip -o > file
sondern auch dascat
quelle
Wenn Sie tun:
Und führen Sie dann die in Ihrem EDIT vorgeschlagene Demo aus. Sie sehen die foo-Leiste im Ausdruck von test.out . Die Zeilendisziplin des Terminals spült seine Ausgabe an den Leser, während es jedes spezielle EOL-Zeichen in Ihrer Eingabe liest .
Ein Linux-Terminal im kanonischen Modus - wie es mit
stty icanon
oder wahrscheinlich nur mit konfiguriert werden kannstty sane
- verarbeitet die folgenden speziellen Eingabezeichen ...^D
^U
^H
(oder möglicherweise@
oder^?
auf einigen Systemen)Wenn iexten auch gesetzt ist - wie
stty icanon iexten
oder wahrscheinlich auch nur -stty sane
, wird ein kanonisches Linux-Terminal auch ...^W
^R
^V
Diese Zeichen werden behandelt, indem sie aus dem Eingabestream entfernt werden - mit Ausnahme von eol und eol2 - und die zugehörige Spezialfunktion ausgeführt werden, bevor der verarbeitete Stream an den Reader übergeben wird. Dies ist normalerweise Ihre Shell, kann aber auch die Vordergrundprozessgruppe sein .
Andere spezielle Eingabezeichen, die ähnlich gehandhabt werden, aber unabhängig von einer beliebigen Einstellung von icanon konfiguriert werden können , umfassen das isig set - set wie
stty isig
und wahrscheinlich auch in einer vernünftigen Konfiguration enthalten:^\
^Z
kill -CONT "$!"
oder nurfg
mit einer (set -m
) jobgesteuerten Shell fortgesetzt werden .^C
Und das ixon- Set - konfiguriert wie
stty ixon
und normalerweise auch in einer vernünftigen Konfiguration enthalten:^S
^Q
Sonderzeichen, die auf anderen Nicht-Linux-Systemen behandelt werden, können sein:
^O
Und möglicherweise...
^@
(Bedeutung\0
oderNUL
)shl
Shell-Layer- Anwendung auf einigen Systemen.shl
die ptys multiplext und daher mit der Auftragssteuerung kompatibel ist, und nicht das swtch- abhängige Verhalten der ursprünglichen Implementierung, kann in derheirloom-toolchest
Tool-Suite frei gewählt werden.Für ein klareres Bild, wie und warum (und vielleicht warum nicht) diese Eingabefunktionen gehandhabt werden, konsultieren Sie
man 3 termios
.Alle oben genannten Funktionen können - falls zutreffend - wie zugewiesen (oder neu zugewiesen) werden
stty
function assigned-key
. Um eine einzelne Funktion zu deaktivieren, gehen Sie wie folgt vor . Alternativ können Sie, wie verschiedene Versuche mit Zuweisungen für eine der oben genannten Zeilenbearbeitungsfunktionen mit allen GNU-, AST- oder Erbstück- Implementierungen zu signalisieren scheinen, als NUL- Zuweisung für eine Funktion angeben, dass sie unter meinem Linux nicht zugewiesen ist System.stty
function
^-
stty
stty
function
^@
Wahrscheinlich sehen Sie ein Echo dieser Zeichen, wenn Sie sie eingeben (wie wahrscheinlich mit [-] ctlecho konfiguriert werden kann ) , aber dies ist nur eine Markierung, die Ihnen zeigt, wo Sie es getan haben - das Programm, das Ihre Eingabe empfängt, hat keine Ahnung, dass Sie es tun Sie haben sie getippt (mit Ausnahme von eol [2] ) und erhalten nur eine Kopie Ihrer Eingabe, auf die die Zeilendisziplin ihre Effekte angewendet hat.
Die Handhabung der verschiedenen Zeilenbearbeitungsfunktionen durch das Terminal hat zur Folge, dass es die Eingabe in gewissem Maße puffern muss, um auf die Funktionen zu reagieren, die Sie ihm anzeigen, dass dies der Fall sein sollte - und daher kann es keine unbegrenzte Zufuhr von Eingaben geben, die Sie könnten jederzeit töten . Der Zeilenpuffer ist genauer gesagt der Kill - Puffer.
Wenn legen Sie die EOL oder EOL2 Zeichen bis zu einem gewissen Trennzeichen , die in der Eingabe auftritt - auch wenn weder ein Newline oder ein Return - Zeichen, zum Beispiel - dann werden Sie nur in der Lage sein , zu töten bis zu dem Punkt , dass es zuletzt aufgetreten und Ihren Kill - Puffer wird so weit wie möglich verlängert, bis die nächste Zeile ( oder eine neue Zeile (oder ein Return, wenn icrnl gesetzt ist und igncr nicht)) in der Eingabe auftritt.
quelle
cat
akzeptiert eine beliebige Anzahl von Zeichen, wie Sie zum Beispiel sehen könntencat /dev/random > test.bin
(tun Sie es nicht, es sei denn, Sie wissen, wie Sie es stoppen können :). Ich habe versucht, eine große Datei zu kopieren und einzufügencat > test.txt
. Alle Zeilen sind in der Datei gelandet, unabhängig davon, ob ich mit Ctrl- coder Ctrl- abgebrochen habe. Im ersten dFall wurden jedoch nicht alle Zeilen auf dem Terminal gedruckt . Ich glaube, das liegt daran, dasscat
der Druckvorgang gepuffert wird und vor jedem Druckvorgang auf einen vollständigen Textpuffer oder eine direkte Eingabe vom Terminal gewartet wird.Auf meinem System glaube ich, dass die Puffergröße 4096 (2 ^ 12) Bytes beträgt: Erstellen Sie eine Datei mit 4095 Bytes
(printf '1234567890%.0s' {1..409} && printf 12345) > test.in
, laden Sie diese mit in den Kopierpufferxclip test.in
, starten Sie siecat > test.out
, fügen Sie sie mit Shift- ein Insertund beenden Sie den Stream mit Ctrl- d. Fügen Sie nun ein Byte mit hinzuprintf '6' >> test.in
, und der Stream wird zweimal gedruckt : Einmal in dercat
Ausgabe (alle 4096 Bytes) und die letzten 4095 Bytes erneut in der Shell nach dem Beenden.quelle
Eine Lösung besteht darin, es in einen Editor einzufügen, der lange Zeilen unterstützt, z. B. vim.
Wenn Sie vim verwenden, rufen Sie zuerst den
:paste
↵Einfügemodus mit auf, bevor Sie den Einfügemodus mit iaufrufen und den Text einfügen .quelle