Mam więc dużo danych BEZ NOWYCH LINII w schowku (jest to duży plik SVG w jednej linii). poszedłem
$ cat >file.svg
następnie próbował wkleić (w Gnome Terminal), ale zaakceptowano tylko pierwsze znaki 4kB.
Zakładam, że jest to funkcja / ograniczenie readline.
Czy istnieje sposób na czytanie ze STDIN, który uniknąłby tego problemu?
EDYTOWAĆ
Przypadek testowy: Utwórz plik demonstracyjny. Ten będzie miał ~ 4k "=" symbole, a następnie "foo bar".
{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Skopiuj to do schowka
xclip test.in
(jeśli chcesz kliknąć środkowy przycisk, aby wstawić) lub
xclip -selection clipboard test.in
(jeśli chcesz użyć Ctrl-Shift-Insert, aby go wkleić)
Następnie cat >test.out
wklej (w dowolny sposób). Naciśnij Ctrl-D, aby zakończyć strumień. cat test.out
- Widzisz „foo bar”?
W mojej konfiguracji (Ubuntu 12.04, Gnome Terminal, zsh) po wklejeniu widzę tylko =
i nie widzę foo bar
. To samo, kiedy sprawdzam test.out
.
Odpowiedzi:
Jeśli dobrze rozumiem źródło, w Linuksie maksymalna liczba znaków, które można odczytać za jednym razem na terminalu, jest określona przez
N_TTY_BUF_SIZE
źródło jądra. Wartość wynosi 4096.Jest to ograniczenie interfejsu terminala, w szczególności trybu kanonicznego („gotowanego”), który zapewnia niezwykle prymitywny edytor linii (backspace, enter, Ctrl+ Dna początku linii dla końca pliku). Dzieje się to całkowicie poza procesem czytania.
Możesz przełączyć terminal do trybu surowego, który wyłącza przetwarzanie linii. Wyłącza również Ctrl+ Di inne drobiazgi, co stanowi dodatkowe obciążenie dla twojego programu.
Jest to starożytne ograniczenie Uniksa, które nigdy nie zostało naprawione, ponieważ motywacja jest niewielka. Ludzie nie wchodzą w tak długie linie. Jeśli podajesz dane wejściowe z programu, przekierujesz dane wejściowe programu z pliku lub potoku.
Na przykład, aby użyć zawartości schowka X, potoku z
xsel
lubxclip
. W Twoim przypadku:Usuń
-b
lub-selection clipboard
użyj zaznaczenia X (tego, które ustawia się poprzez podświetlenie myszą) zamiast schowka.W systemie OSX użyj przycisku,
pbpaste
aby wkleić zawartość schowka (ipbcopy
ustawić ją).Możesz uzyskać dostęp do schowka X przez SSH, jeśli aktywujesz przekazywanie X11 za pomocą
ssh -X
(którego niektóre serwery mogą zabronić). Jeśli można użyć tylkossh
bez spedycji X11 można użyćscp
,sftp
lubsshfs
skopiować plik.Jeśli wklejanie jest jedynym rozwiązaniem, ponieważ nie możesz przesłać schowka lub nie wklejasz, ale np. Fałszujesz pisanie na maszynie wirtualnej, alternatywnym podejściem jest zakodowanie danych w coś, co ma nowe znaki. Base64 jest do tego odpowiedni: przekształca dowolne dane w znaki drukowalne i ignoruje białe znaki podczas dekodowania. Podejście to ma tę dodatkową zaletę, że obsługuje dowolne dane na wejściu, a nawet znaki sterujące, które terminal interpretuje podczas wklejania. W twoim przypadku możesz zakodować treść:
następnie dekoduj:
źródło
xsel
> 4k bajtów występuje naprawdę paskudny błąd powodującyLimit używasz na to rozmiar maksymalny linii w trybie wejściowym kanonicznej ,
MAX_CANON
.W trybie wprowadzania kanonicznego sterownik tty zapewnia podstawowe usługi edycji linii, więc program przestrzeni użytkownika nie musi tego robić. Nie ma prawie tyle funkcji, co readline, ale rozpoznaje kilka konfigurowalnych znaków specjalnych, takich jak wymazywanie (zwykle Backspace lub Delete) i zabijanie (zwykle Ctrl-U).
Najważniejsze dla twojego pytania, buforuje tryb kanoniczny, dopóki nie pojawi się znak końca linii. Ponieważ bufor znajduje się w sterowniku tty, w pamięci jądra nie jest bardzo duży.
Możesz wyłączyć tryb kanoniczny za pomocą
stty cbreak
lubstty -icanon
, a następnie wkleić. Ma to tę istotną wadę, że nie będziesz w stanie wysłać EOF za pomocą Ctrl-D. To kolejna z rzeczy, za które odpowiada tryb kanoniczny. Nadal będziesz mógł zakończyćcat
Ctrl-C, ponieważ znaki generujące sygnał są kontrolowane przez oddzielną flagę (stty raw
lubstty -isig
).Tajemnicą dla mnie jest to, dlaczego skoro już wykazałeś, że wiesz o tym
xclip
, nie używasz tylkoxclip -o > file
zamiastcat
źródło
Jeśli zrobisz:
A następnie uruchom demo sugerowane w EDIT , zobaczysz pasek foo na wydruku test.out . Dyscyplina liniowa terminala opróżni swoje wyjście do swojego czytnika, gdy odczytuje każdy specjalny znak eol z twojego wejścia.
Terminal trybu kanonicznego w systemie Linux - jak można skonfigurować za pomocą
stty icanon
lub prawdopodobnie po prostustty sane
- obsługuje następujące specjalne znaki wejściowe ...^D
^U
^H
(lub ewentualnie@
lub^?
w niektórych systemach)Gdy iexten jest również ustawiony - podobnie jak
stty icanon iexten
, a może znowu tylkostty sane
kanoniczny terminal Linux, będzie obsługiwał ...^W
^R
^V
Te znaki są obsługiwane przez usunięcie ich ze strumienia wejściowego - z wyjątkiem eol i eol2 , czyli - i wykonanie powiązanej funkcji specjalnej przed przekazaniem przetworzonego strumienia do czytnika - co zwykle jest twoją powłoką, ale może być niezależnie od grupy procesów pierwszego planu. .
Inne specjalne znaki wejściowe, które są obsługiwane podobnie, ale mogą być konfigurowane niezależnie od dowolnego ustawienia icanon , obejmują zestaw isig - zestaw podobny
stty isig
i prawdopodobnie również zawarty w zdrowej konfiguracji:^\
^Z
kill -CONT "$!"
lub tylkofg
w (set -m
) kontrolowanej przez powłokę powłoce.^C
I zestaw ixon - skonfigurowany jak
stty ixon
i zwykle zawarty w zdrowej konfiguracji:^S
^Q
Znaki specjalne obsługiwane w innych systemach innych niż Linux mogą obejmować ...
^O
I ewentualnie...
^@
(znaczenie\0
lubNUL
)shl
warstw powłoki w niektórych systemach.shl
która multipleksuje ptys i dlatego jest kompatybilna z kontrolą zadań, a nie z zachowaniem zależnym od switch oryginalnej implementacji, może być swobodnie dostępna wheirloom-toolchest
pakiecie narzędzi.Aby uzyskać wyraźniejszy obraz tego, jak i dlaczego (a może dlaczego nie) obsługiwane są te funkcje wprowadzania, zapoznaj się z
man 3 termios
.Wszystkie powyższe funkcje można przypisać (lub ponownie przypisać) - w stosownych przypadkach - podobnie
stty
function assigned-key
. Aby wyłączyć dowolną pojedynczą funkcję, wykonaj . Alternatywnie, ponieważ różne próby przypisania dowolnej z wyżej wymienionych funkcji edycji linii ze wszystkimi implementacjami GNU, AST lub dziedzicami wydają się wskazywać, możesz również, ponieważ przypisanie NUL dla dowolnej funkcji wydaje się równoznaczne z ustawieniem jej jako nieprzypisanej w moim systemie Linux system.stty
function
^-
stty
stty
function
^@
Prawdopodobnie widzisz echo tych znaków podczas ich wpisywania (co można prawdopodobnie skonfigurować w / [-] ctlecho ) , ale jest to tylko znacznik pokazujący, gdzie zrobiłeś - program otrzymujący twoje dane wejściowe nie ma pojęcia, że ty wpisałem je (z wyjątkiem eol [2] , to jest) i otrzymuje tylko kopię twojego wkładu, do którego dyscyplina liniowa zastosowała swoje efekty.
Konsekwencją obsługi różnych funkcji edycji linii przez terminal jest to, że musi on w pewnym stopniu buforować dane wejściowe, aby działać zgodnie z funkcjami, które mu wskażesz - i dlatego nie może istnieć nieograniczona ilość danych wejściowych, które możesz w dowolnym momencie zabić . Linia bufor jest dokładniej kill bufor.
Jeśli ustawisz znaki eol lub eol2 na jakiś separator występujący na wejściu - nawet jeśli na przykład nie jest on znakiem nowej linii ani znakiem powrotu - będziesz w stanie zabić tylko do momentu, w którym ostatnio wystąpił i bufor zabijania będzie rozciągać się tak daleko, jak to możliwe, dopóki następna z nich - lub nowa linia (lub powróci, jeśli icrnl jest ustawione, a igncr nie jest ustawione ) - pojawi się na wejściu.
źródło
cat
zaakceptuje dowolną liczbę znaków, jak można to zrobić na przykładcat /dev/random > test.bin
(nie rób tego, chyba że wiesz, jak to zatrzymać :). Próbowałem skopiować i wkleić duży plik docat > test.txt
. Wszystkie linie znalazły się w pliku, niezależnie od tego, czy anulowałem za pomocą Ctrl- cczy Ctrl- d, ale w pierwszym przypadku nie wszystkie linie zostały wydrukowane na terminalu . Uważam, żecat
dzieje się tak, ponieważ buforuje drukowanie, czekając na pełny bufor tekstu lub bezpośrednie wejście z terminala przed każdym drukowaniem.W moim systemie rozmiar bufora wynosi 4096 (2 ^ 12) bajtów: utwórz plik 4095 bajtów za pomocą
(printf '1234567890%.0s' {1..409} && printf 12345) > test.in
, załaduj go do bufora kopii za pomocąxclip test.in
, uruchomcat > test.out
, wklej za pomocą Shift- Inserti zakończ strumień, naciskając Ctrl- d. Teraz dodaj bajt za pomocąprintf '6' >> test.in
, a strumień zostanie wydrukowany dwukrotnie : Raz wcat
wyjściu (wszystkie 4096 bajtów), a ostatnie 4095 bajtów ponownie w powłoce po zakończeniu.źródło
Jednym z rozwiązań jest wklejenie go do edytora, który obsługuje długie linie, na przykład vim.
Jeśli używasz vima, najpierw wejdź w tryb wklejania,
:paste
↵zanim przejdziesz do trybu wstawiania izi wklejania tekstu.źródło