Así que tengo muchos datos SIN NUEVAS LÍNEAS en el portapapeles (es un archivo SVG grande en una línea). Yo fuí
$ cat >file.svg
Luego traté de pegar (en Gnome Terminal), pero solo se aceptaron los primeros 4kB caracteres.
Supongo que esta es una característica / limitación de readline.
¿Hay alguna manera de leer de STDIN que evite este problema?
EDITAR
Caso de prueba: cree un archivo de demostración. Este tendrá ~ 4k "=" símbolos seguidos de "foo bar".
{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Copia eso en tu portapapeles
xclip test.in
(si desea hacer clic con el botón central para insertar) o
xclip -selection clipboard test.in
(si quieres usar Ctrl-Shift-Insert para pegarlo)
Luego cat >test.out
, pegue (de cualquier manera). Presione Ctrl-D para finalizar la transmisión. cat test.out
- ¿Ves "foo bar"?
En mi configuración (Ubuntu 12.04, Terminal Gnome, zsh) cuando pego solo veo =
y no veo foo bar
. Lo mismo cuando inspecciono test.out
.
Respuestas:
Si entiendo la fuente correctamente, en Linux, la cantidad máxima de caracteres que se pueden leer de una vez en un terminal está determinada por
N_TTY_BUF_SIZE
la fuente del núcleo. El valor es 4096.Esta es una limitación de la interfaz del terminal, específicamente el modo canónico ("cocinado") que proporciona un editor de líneas extremadamente crudo (retroceso, enter, Ctrl+ Dal comienzo de una línea para el final del archivo). Sucede completamente fuera del proceso que está leyendo.
Puede cambiar el terminal al modo sin procesar, que deshabilita el procesamiento de línea. También deshabilita Ctrl+ Dy otras sutilezas, lo que supone una carga adicional para su programa.
Esta es una antigua limitación de Unix que nunca se ha solucionado porque hay poca motivación. Los humanos no entran en filas tan largas. Si alimentara la entrada de un programa, redirigiría la entrada de su programa desde un archivo o una tubería.
Por ejemplo, para usar el contenido del portapapeles X, canalizar desde
xsel
oxclip
. En tu caso:Elimine
-b
o-selection clipboard
use la selección X (la que se establece resaltando con el mouse) en lugar del portapapeles.En OSX, use
pbpaste
para pegar el contenido del portapapeles (ypbcopy
para configurarlo).Puede acceder al portapapeles X a través de SSH si activa el reenvío X11 con
ssh -X
(que algunos servidores pueden prohibir). Si sólo se puede utilizarssh
sin el reenvío por X11, puede utilizarscp
,sftp
osshfs
para copiar un archivo.Si pegar es la única solución porque no puede reenviar el portapapeles o no está pegando pero, por ejemplo, falsificando la escritura en una máquina virtual, un enfoque alternativo es codificar los datos en algo que tenga nuevas líneas. Base64 es adecuado para esto: transforma datos arbitrarios en caracteres imprimibles e ignora los espacios en blanco al decodificar. Este enfoque tiene la ventaja adicional de que admite datos arbitrarios en la entrada, incluso caracteres de control que el terminal interpretaría al pegar. En su caso, puede codificar el contenido:
luego descifrarlo:
fuente
xsel
con> 4k bytes: github.com/kfish/xsel/issues/14El límite que se está ejecutando en es el tamaño máximo de una línea en modo de entrada canónica ,
MAX_CANON
.En el modo de entrada canónica, el controlador tty proporciona servicios básicos de edición de línea para que el programa de espacio de usuario no lo necesite. No tiene casi tantas características como readline, pero reconoce algunos caracteres especiales configurables como borrar (generalmente Retroceso o Eliminar) y matar (generalmente Ctrl-U).
Lo más importante para su pregunta, el modo canónico amortigua la entrada hasta que se ve el carácter de fin de línea. Debido a que el búfer está en el controlador tty, en la memoria del kernel, no es muy grande.
Puede desactivar el modo canónico con
stty cbreak
ostty -icanon
, y luego pegar. Esto tiene la desventaja significativa de que no podrá enviar un EOF con Ctrl-D. Esa es otra de las cosas de las que es responsable el modo canónico. Aún podrá terminarcat
con Ctrl-C porque los caracteres generadores de señal están controlados por una bandera separada (stty raw
ostty -isig
).El misterio para mí es por qué, dado que ya has demostrado que sabes
xclip
, no solo usasxclip -o > file
elcat
fuente
Si lo haces:
Y luego ejecute la demostración sugerida en su EDIT , verá la barra de información en la impresión de test.out . La disciplina de línea del terminal vaciará su salida a su lector a medida que lea cada charol especial en su entrada.
Un terminal de modo canónico de Linux, como se puede configurar con
stty icanon
o probablemente solostty sane
, maneja los siguientes caracteres de entrada especiales ...^D
^U
^H
(o posiblemente@
o^?
en algunos sistemas)Cuando iexten también está configurado, como
stty icanon iexten
, o nuevamente, probablemente solostty sane
, un terminal canónico de Linux también manejará ...^W
^R
^V
Estos caracteres se manejan eliminándolos de la secuencia de entrada, a excepción de eol y eol2 , es decir, y realizando la función especial asociada antes de pasar la secuencia procesada al lector, que generalmente es su shell, pero podría ser cualquier grupo de procesos en primer plano .
Otros caracteres de entrada especiales que se manejan de manera similar pero que se pueden configurar independientemente de cualquier configuración de icanon incluyen el conjunto de isig , configurado como
stty isig
y probablemente también incluido en una configuración sensata :^\
^Z
kill -CONT "$!"
ofg
en un (set -m
) shell controlado por trabajo.^C
Y el conjunto ixon , configurado como
stty ixon
y también generalmente incluido en una configuración sensata :^S
^Q
Los caracteres especiales manejados en otros sistemas que no son Linux pueden incluir ...
^O
Y posiblemente...
^@
(significado\0
oNUL
)shl
capas de shell en algunos sistemas.shl
que multiplexa ptys y, por lo tanto, es compatible con el control del trabajo en lugar del comportamiento dependiente de swtch de la implementación original se puede tener libremente en elheirloom-toolchest
conjunto de herramientas.Para obtener una imagen más clara de cómo y por qué (y quizás por qué no) se manejan estas funciones de entrada, consulte
man 3 termios
.Todas las funciones anteriores se pueden asignar (o reasignar) , cuando corresponda, como
stty
function assigned-key
. Para deshabilitar cualquier función individual, haga . Alternativamente, como varios intentos con asignaciones para cualquiera de las funciones de edición de líneas mencionadas anteriormente con todas las implementaciones de GNU, AST o reliquia parecen indicar, también puede, como la asignación NUL para cualquier función parece ser equivalente a configurarla como no asignada en mi Linux sistema.stty
function
^-
stty
stty
function
^@
Probablemente ve un eco de estos caracteres cuando los escribe (como se puede configurar probablemente con [-] ctlecho ) , pero esto es solo un marcador que le muestra dónde lo hizo: el programa que recibe su entrada no tiene noción de que usted los escribió (excepto eol [2] , es decir) y recibe solo una copia de su entrada a la que la disciplina de línea ha aplicado sus efectos.
Una consecuencia del manejo por parte del terminal de las diversas funciones de edición de línea es que debe necesitar un buffer de entrada hasta cierto punto para actuar sobre las funciones que le indique que debería, y por lo tanto no puede haber un suministro ilimitado de entrada que podrías matar en cualquier momento . El buffer de línea es más precisamente el buffer de eliminación .
Si establece los caracteres eol o eol2 en algún delimitador que se produce en la entrada, incluso si ninguno es una línea nueva o un carácter de retorno, por ejemplo, solo podrá matar hasta el punto en que ocurrió por última vez y su búfer de muerte se extenderá tanto como sea posible hasta que se produzca el siguiente de estos, o una nueva línea (o regrese si icrnl está configurado y no está activado igncr ) en la entrada.
fuente
cat
aceptará cualquier número de caracteres, como puede observar haciendo, por ejemplocat /dev/random > test.bin
(no lo haga a menos que sepa cómo detenerlo :). Intenté copiar y pegar un archivo grande encat > test.txt
. Todas las líneas terminaron en el archivo si cancelé con Ctrl- co Ctrl- d, pero en el primer caso no todas las líneas se imprimieron en el terminal . Creo que esto se debe a quecat
amortigua su impresión, esperando un buffer completo de texto o entrada directa desde el terminal antes de cada impresión.En mi sistema, creo que el tamaño del búfer es 4096 (2 ^ 12) bytes: cree un archivo de 4095 bytes
(printf '1234567890%.0s' {1..409} && printf 12345) > test.in
, cárguelo en el búfer de copia usandoxclip test.in
, iniciecat > test.out
, pegue usando Shift- Inserty finalice la secuencia presionando Ctrl- d. Ahora agregue un byte usandoprintf '6' >> test.in
, y la secuencia se imprime dos veces : una vez en lacat
salida (todos los 4096 bytes), y los últimos 4095 bytes nuevamente en el shell después de terminar.fuente
Una solución es pegarlo en un editor que admita líneas largas, por ejemplo vim.
Si usa vim, primero ingrese al modo pegar con
:paste
↵antes de ingresar al modo insertar con iy pegue el texto.fuente