如何在终端上没有换行的情况下读取超过 4k 的输入?

art*_*bot 33 terminal clipboard

所以我在剪贴板上有很多没有新行的数据(一行是一个大的 SVG 文件)。我去了

$ cat >file.svg
Run Code Online (Sandbox Code Playgroud)

然后尝试粘贴(在 Gnome 终端中),但只接受前 4kB 字符。

我认为这是一个 readline 功能/限制。

有没有办法从 STDIN 读取可以避免这个问题?

编辑

测试用例:创建一个演示文件。这个将有~4k“=”符号后跟“foo bar”。

{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Run Code Online (Sandbox Code Playgroud)

将其复制到剪贴板

xclip test.in
Run Code Online (Sandbox Code Playgroud)

(如果你想中键插入)或

xclip -selection clipboard test.in
Run Code Online (Sandbox Code Playgroud)

(如果您想使用 Ctrl-Shift-Insert 将其粘贴进去)

然后cat >test.out,粘贴(无论哪种方式)。按 Ctrl-D 结束流。cat test.out- 你看到“foo bar”了吗?

在我的设置(Ubuntu 12.04、Gnome 终端、zsh)上粘贴时,我只=看到foo bar. 我检查时也一样test.out

Gil*_*il' 31

如果我正确理解源代码,在Linux下,终端上一次可以读取的最大字符数由N_TTY_BUF_SIZE内核源代码决定。该是4096。

这是终端界面的限制,特别是规范(“cooked”)模式,它提供了一个极其粗糙的行编辑器(退格、回车、Ctrl+D在行首用于文件结束)。它完全发生在阅读过程之外。

您可以将终端切换到原始模式,从而禁用线路处理。它还会禁用Ctrl+D和其他细节,给您的程序带来额外的负担。

这是一个古老的 Unix 限制,从未被修复,因为没有什么动力。人类不会排这么长的队。如果您从程序中输入输入,您将从文件或管道中重定向程序的输入。

例如,要使用 X 剪贴板的内容,管道来自xselxclip。在你的情况下:

xsel -b >file.svg
xclip -selection clipboard >file.svg
Run Code Online (Sandbox Code Playgroud)

删除-b-selection clipboard使用 X 选择(通过用鼠标突出显示的选择)而不是剪贴板。

在 OSX 上,用于pbpaste粘贴剪贴板内容(并对其pbcopy进行设置)。

如果您激活 X11 转发ssh -X(某些服务器可能禁止),您可以通过 SSH 访问 X 剪贴板。如果只能在ssh没有 X11 转发的情况下使用scp,则可以使用,sftpsshfs复制文件。

如果粘贴是唯一的解决方案,因为您无法转发剪贴板,或者您不粘贴但例如在虚拟机中假装键入,则另一种方法是将数据编码为具有换行符的内容。Base64非常适合于此:它将任意数据转换为可打印字符,并在解码时忽略空格。这种方法还有一个额外的优势,它支持输入中的任意数据,甚至是终端在粘贴时解释的控制字符。在您的情况下,您可以对内容进行编码:

xsel -b | base64 | xsel -b
Run Code Online (Sandbox Code Playgroud)

然后解码它:

base64 -d
 Paste
Ctrl+D

  • 请注意,使用大于 4k 字节的“xsel”时会出现非常严重的数据损坏错误:https://github.com/kfish/xsel/issues/14 (2认同)

小智 19

您遇到的限制是规范输入模式下一行的最大大小, MAX_CANON

在规范输入模式下,tty 驱动程序提供基本的行编辑服务,因此用户空间程序不需要。它没有 readline 那么多的功能,但它可以识别一些可配置的特殊字符,如擦除(通常是退格或删除)和杀死(通常是 Ctrl-U)。

对于您的问题最重要的是,规范模式会缓冲输入,直到看到行尾字符。因为缓冲区在 tty 驱动程序中,在内核内存中,它不是很大。

您可以使用stty cbreak或关闭规范模式stty -icanon,然后进行粘贴。这有一个明显的缺点,即您将无法使用 Ctrl-D 发送 EOF。这是规范模式负责的另一件事。您仍然可以cat使用 Ctrl-C终止 ,因为信号生成字符由单独的标志(stty rawstty -isig)控制。

对我来说神秘的是为什么,既然你已经证明你知道xclip,你不只是使用xclip -o > file代替cat

  • 啊,好的旧上传粘贴。如果我必须执行其中之一并且它不是纯文本,我会对其进行 uuencode,而不是试图说服 tty 驱动程序通过它。带有大量行的纯文本也可以这样处理。 (3认同)
  • 这个谜团很容易解开:似乎artfulrobot 想用剪贴板中的数据快速填充远程主机上的文件。在远程 shell 中,通常无法通过 xclip 直接访问本地剪贴板。 (2认同)