web-dev-qa-db-ja.com

端末で改行せずに4k入力を読み取る方法は?

クリップボードに大量のデータWITHOUT NEW LINESがあります(1行に大きなSVGファイルがあります)。私は行った

$ cat >file.svg

次に、(Gnomeターミナルで)貼り付けを試みましたが、最初の4kB文字のみが受け入れられました。

これはreadlineの機能/制限だと思います。

この問題を回避するSTDINから読み取る方法はありますか?

編集

テストケース:デモファイルを作成します。これには、〜4kの「=」記号の後に「foo bar」が続きます。

{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in

それをクリップボードにコピーします

xclip test.in

(中クリックして挿入する場合)または

xclip -selection clipboard test.in

(Ctrl-Shift-Insertを使用して貼り付ける場合)

次にcat >test.out、貼り付け(どちらの方法でも)。 Ctrl-Dを押してストリームを終了します。 cat test.out-「foo bar」が表示されますか?

私のセットアップ(Ubuntu 12.04、Gnomeターミナル、zsh)では、貼り付けたときに=と表示されないfoo bar。検査するときも同じですtest.out

25
artfulrobot

私がソースを正しく理解している場合、Linuxでは、端末で一度に読み取ることができる最大文字数は、カーネルソースの N_TTY_BUF_SIZE によって決まります。 は4096です。

これはターミナルインターフェイスの制限です。具体的には canonical(「cooked」)モード であり、非常に粗雑な行エディタ(バックスペース、Enter、 Ctrl+D ファイルの終わりの行の先頭)。それは読んでいるプロセスの完全に外側で起こります。

端末をrawモードに切り替えることができます。これにより、ライン処理が無効になります。それも無効にします Ctrl+D プログラムに余分な負担をかけるなど、その他の機能。

これは、やる気がほとんどないために修正されなかったUnixの古代の制限です。人間はそのような長い列には入らない。プログラムから入力を供給している場合は、プログラムの入力をファイルまたはパイプからリダイレクトします。

たとえば、Xクリップボードのコンテンツを使用するには、 xsel または xclip からパイプします。あなたの場合:

xsel -b >file.svg
xclip -selection clipboard >file.svg

-bまたは-selection clipboardを削除して、クリップボードではなくX選択(マウスで強調表示して設定されたもの)を使用します。

OSXでは、 pbpaste を使用してクリップボードの内容を貼り付けます(およびpbcopyを使用して設定します)。

ssh -X(一部のサーバーでは禁止されている場合があります)を使用してX11転送をアクティブ化すると、SSH経由でXクリップボードにアクセスできます。 X11転送なしでsshのみを使用できる場合は、scpsftpまたはsshfsを使用してファイルをコピーできます。

クリップボードを転送できない、または貼り付けていないために貼り付けが唯一の解決策である場合、たとえば仮想マシンへのタイピングを偽って、別のアプローチはデータを改行があるものにエンコードすることです。 Base64 はこれに適しています。任意のデータを印刷可能な文字に変換し、デコード時に空白を無視します。このアプローチには、貼り付け時に端末が解釈する制御文字でさえ、入力内の任意のデータをサポートするという追加の利点があります。あなたのケースでは、コンテンツをエンコードできます:

xsel -b | base64 | xsel -b

それをデコードします:

 base64 -d 
PasteCtrl+D

あなたが遭遇している制限は、 正規入力モードMAX_Canonでの行の最大サイズです。

正規入力モードでは、ttyドライバーは基本的な行編集サービスを提供するため、ユーザー空間プログラムは必要ありません。 readlineほど多くの機能はありませんが、erase(通常はBackspaceまたはDelete)やkill(通常はCtrl-U)などのいくつかの構成可能な特殊文字を認識します。

質問にとって最も重要なのは、正規モードは行末文字が見つかるまで入力をバッファリングすることです。バッファはttyドライバ内、カーネルメモリ内にあるため、それほど大きくありません。

stty cbreakまたはstty -icanonを使用して正規モードをオフにしてから、貼り付けることができます。これには、EOFをCtrl-Dで送信できないという重大な欠点があります。これは、正規モードが担当するもう1つのことです。それでも、信号生成文字は別のフラグ(stty rawまたはstty -isig)によって制御されるため、Ctrl-Cを使用したcat

私にとってミステリーは、あなたがxclipについて知っていることをすでに示したので、catの代わりにxclip -o > fileを使用するだけではない理由です。

14
user41515

catは、たとえばcat /dev/random > test.binを実行することで確認できるように、任意の数の文字を受け入れます(停止する方法がわからない場合は、実行しないでください:)。 大きなファイルcat > test.txtにコピーして貼り付けてみました。キャンセルしたかどうかに関係なく、すべての行がファイルに含まれていました Ctrl-c または Ctrl-d、しかし前者の場合すべての行が端末に出力されるわけではありません。これは、catが印刷をバッファリングし、各印刷の前に端末からのテキストまたは直接入力の完全なバッファを待機するためと考えています。

私のシステムでは、バッファサイズは4096(2 ^ 12)バイトだと思います: (printf '1234567890%.0s' {1..409} && printf 12345) > test.in を使用して4095バイトのファイルを作成し、xclip test.inを使用してコピーバッファにロードします、cat > test.outを起動し、次を使用して貼り付け Shift-Insertを押してストリームを終了します Ctrl-d。次に、printf '6' >> test.inを使用してバイトを追加すると、ストリームが出力されますtwicecat出力(すべて4096バイト)に1回、および終了後、シェル上で最後の4095バイト

1
l0b0

1つの解決策は、vimなどの長い行をサポートするエディターに貼り付けることです。

Vimを使用する場合は、最初に:pasteを使用して貼り付けモードに入ります で挿入モードに入る前 i テキストを貼り付けます。

0
Hjulle