Portanto, tenho muitos dados SEM NOVAS LINHAS na área de transferência (é um arquivo SVG grande em uma linha). eu fui
$ cat >file.svg
depois tentou colar (no Gnome Terminal), mas apenas os primeiros caracteres de 4kB foram aceitos.
Presumo que este seja um recurso / limitação de readline.
Existe uma maneira de ler o STDIN que evite esse problema?
EDITAR
Caso de teste: Crie um arquivo de demonstração. Este terá ~ 4k "=" símbolos seguidos por "foo bar".
{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Copie isso para a área de transferência
xclip test.in
(se você quiser clicar com o botão do meio para inserir) ou
xclip -selection clipboard test.in
(se você quiser usar Ctrl-Shift-Insert para colar)
Em seguida cat >test.out
, cole (de qualquer maneira). Pressione Ctrl-D para finalizar o fluxo. cat test.out
- você vê "foo bar"?
Na minha instalação (Ubuntu 12.04, Gnome Terminal, zsh), quando colo, vejo apenas o =
e não vejo foo bar
. Mesmo quando inspeciono test.out
.
Respostas:
Se eu entendo a fonte corretamente, no Linux, o número máximo de caracteres que podem ser lidos de uma só vez em um terminal é determinado pela
N_TTY_BUF_SIZE
fonte do kernel. O valor é 4096.Essa é uma limitação da interface do terminal, especificamente o modo canônico ("cozido"), que fornece um editor de linhas extremamente bruto (backspace, enter, Ctrl+ Dno início de uma linha para o final do arquivo). Isso acontece inteiramente fora do processo que está sendo lido.
Você pode alternar o terminal para o modo bruto, o que desativa o processamento de linha. Ele também desativa Ctrl+ De outras sutilezas, sobrecarregando seu programa.
Esta é uma antiga limitação do Unix que nunca foi corrigida porque há pouca motivação. Os seres humanos não entram nessas longas filas. Se você estivesse alimentando a entrada de um programa, redirecionaria a entrada do programa a partir de um arquivo ou canal.
Por exemplo, para usar o conteúdo da área de transferência do X, canalize de
xsel
ouxclip
. No seu caso:Remova
-b
ou-selection clipboard
use a seleção X (aquela que é definida destacando com o mouse) em vez da área de transferência.No OSX, use
pbpaste
para colar o conteúdo da área de transferência (epbcopy
configurá-lo).Você pode acessar a área de transferência do X por SSH se ativar o encaminhamento do X11
ssh -X
(o que alguns servidores podem proibir). Se você só pode usarssh
sem encaminhamento X11, você pode usarscp
,sftp
ousshfs
para copiar um arquivo.Se colar é a única solução, porque você não pode encaminhar a área de transferência ou não está colando, mas, por exemplo, falsificando a digitação em uma máquina virtual, uma abordagem alternativa é codificar os dados em algo que tenha novas linhas. Base64 é adequado para isso: transforma dados arbitrários em caracteres imprimíveis e ignora os espaços em branco ao decodificar. Essa abordagem tem a vantagem adicional de suportar dados arbitrários na entrada, até controlar caracteres que o terminal interpretaria ao colar. No seu caso, você pode codificar o conteúdo:
então decodifique:
fonte
xsel
com> 4K bytes: github.com/kfish/xsel/issues/14O limite você está correndo em é o tamanho máximo de uma linha no modo de entrada canônica ,
MAX_CANON
.No modo de entrada canônica, o driver tty fornece serviços básicos de edição de linha, para que o programa de espaço do usuário não precise. Ele não possui tantos recursos quanto a linha de leitura, mas reconhece alguns caracteres especiais configuráveis como apagar (geralmente Backspace ou Delete) e kill (geralmente Ctrl-U).
Mais importante para sua pergunta, o modo canônico armazena em buffer até que o caractere de fim de linha seja visto. Como o buffer está no driver tty, na memória do kernel, não é muito grande.
Você pode desativar o modo canônico com
stty cbreak
oustty -icanon
e, em seguida, cole. Isso tem a desvantagem significativa de que você não poderá enviar um EOF com Ctrl-D. Essa é outra das coisas pelas quais o modo canônico é responsável. Você ainda poderá finalizarcat
com Ctrl-C porque os caracteres geradores de sinal são controlados por um sinalizador separado (stty raw
oustty -isig
).O mistério para mim é por que, como você já demonstrou ter conhecimento
xclip
, não usa apenasxclip -o > file
ocat
fonte
Se você fizer:
E, em seguida, execute a demonstração sugerida na sua edição , você verá a barra foo na impressão de test.out . A disciplina de linha do terminal liberará sua saída para o leitor à medida que ele lê cada caractere eol especial em sua entrada.
Um terminal de modo canônico do Linux - como pode ser configurado com
stty icanon
ou provavelmente apenasstty sane
- lida com os seguintes caracteres de entrada especiais ...^D
^U
^H
(ou possivelmente@
ou^?
em alguns sistemas)Quando o iexten também é configurado - como
stty icanon iexten
ou, novamente, provavelmente apenasstty sane
, um terminal canônico do Linux também manipula ...^W
^R
^V
Esses caracteres são manipulados removendo-os do fluxo de entrada - exceto eol e eol2 , ou seja - e executando a função especial associada antes de passar o fluxo processado para o leitor - que geralmente é seu shell, mas pode ser o grupo de processos em primeiro plano. .
Outros caracteres de entrada especiais que são tratados de maneira semelhante, mas podem ser configurados independentemente de qualquer configuração icanon , incluem o isig set - set like
stty isig
e provavelmente também incluído em uma configuração sã :^\
^Z
kill -CONT "$!"
ou apenasfg
em um (set -m
) shell controlado por tarefa.^C
E o conjunto ixon - configurado como
stty ixon
e também geralmente incluído em uma configuração sã :^S
^Q
Caracteres especiais manipulados em outros sistemas não Linux podem incluir ...
^O
E possivelmente...
^@
(significado\0
ouNUL
)shl
shell-layers em alguns sistemas.shl
que multiplexa ptys e, portanto, é compatível com o controle de tarefas, em vez do comportamento dependente de swtch da implementação original, pode ser livremente realizada noheirloom-toolchest
conjunto de ferramentas.Para uma imagem mais clara de como e por que (e talvez por que não) essas funções de entrada são tratadas, consulte
man 3 termios
.Todas as funções acima podem ser atribuídas (ou reatribuídas) - quando aplicável - como
stty
function assigned-key
. Para desativar qualquer função única, faça . Como alternativa, como várias tentativas com atribuições para qualquer uma das funções de edição de linha mencionadas acima, com todas as implementações do GNU, AST ou da herança parecem indicar, você também pode, pois a atribuição NUL para qualquer função parece equiparar a configuração não atribuída no meu linux sistema.stty
function
^-
stty
stty
function
^@
Provavelmente, você vê um eco desses caracteres ao digitá-los (como provavelmente pode ser configurado com [-] ctlecho ) , mas esse é apenas um marcador para mostrar a você o local onde você fez - o programa que recebe sua entrada não faz ideia de que você digitou-os (exceto eol [2] , isto é) e recebe apenas uma cópia de sua entrada na qual a disciplina de linha aplicou seus efeitos.
Uma conseqüência do manuseio do terminal das várias funções de edição de linha é que ele precisa proteger a entrada até certo ponto, a fim de atuar sobre as funções que você indicar que deveria - e, portanto, não pode haver um suprimento ilimitado de entrada que você pode a qualquer momento matar . A linha de tampão é mais precisamente a matança tampão.
Se você definir as EOL ou eol2 caracteres para alguns delimitador que ocorre na entrada - mesmo que nem é uma nova linha ou um caractere de retorno, por exemplo - então você só vai ser capaz de matar até o ponto que ocorreu pela última vez e sua matança tampão vai se estender o máximo possível até a próxima - ou uma nova linha (ou retornar se icrnl estiver definido e igncr não) - ocorrer na entrada.
fonte
cat
aceitará qualquer número de caracteres, como você pode testemunhar, por exemplocat /dev/random > test.bin
(não faça isso a menos que saiba como pará-lo :). Eu tentei copiar e colar um arquivo grande emcat > test.txt
. Todas as linhas terminaram no arquivo se eu cancelei com Ctrl- cou Ctrl- d, mas no primeiro caso, nem todas as linhas foram impressas no terminal . Acredito que isso ocorre porque ocat
buffer é impresso, aguardando um buffer completo de texto ou entrada direta do terminal antes de cada impressão.No meu sistema, acho que o tamanho do buffer é 4096 (2 ^ 12) bytes: Crie um arquivo de 4095 bytes usando
(printf '1234567890%.0s' {1..409} && printf 12345) > test.in
, carregue-o no buffer de cópia usandoxclip test.in
, iniciecat > test.out
, cole usando Shift- Inserte encerre o fluxo pressionando Ctrl- d. Agora adicione um byte usandoprintf '6' >> test.in
, e o fluxo será impresso duas vezes : Uma vez nacat
saída (todos os 4096 bytes) e os últimos 4095 bytes novamente no shell após o término.fonte
Uma solução é colá-lo em um editor que suporte linhas longas, por exemplo, vim.
Se você usar o vim, primeiro entre no modo de colar com
:paste
↵antes de entrar no modo de inserção ie colar o texto.fonte