Jadi saya punya banyak data TANPA GARIS BARU di clipboard (ini adalah file SVG besar pada satu baris). saya pergi
$ cat >file.svg
kemudian mencoba menempel (di Terminal Gnome), tetapi hanya karakter 4kB pertama yang diterima.
Saya menganggap ini adalah fitur / batasan readline.
Apakah ada cara untuk membaca dari STDIN yang akan menghindari masalah ini?
EDIT
Test case: Buat file demo. Yang ini akan memiliki ~ 4k "=" simbol diikuti oleh "bilah foo".
{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in
Salin itu ke clipboard Anda
xclip test.in
(jika Anda ingin klik tengah untuk menyisipkan) atau
xclip -selection clipboard test.in
(jika Anda ingin menggunakan Ctrl-Shift-Insert untuk melewatinya)
Kemudian cat >test.out
, rekatkan (bagaimanapun caranya). Tekan Ctrl-D untuk mengakhiri streaming. cat test.out
- Apakah kamu melihat "foo bar"?
Pada pengaturan saya (Ubuntu 12.04, Gnome Terminal, zsh) ketika saya tempel saya hanya melihat =
dan saya tidak melihat foo bar
. Sama ketika saya memeriksa test.out
.
Jawaban:
Jika saya memahami sumbernya dengan benar, di Linux, jumlah karakter maksimum yang dapat dibaca dalam sekali jalan terminal ditentukan oleh
N_TTY_BUF_SIZE
dalam sumber kernel. The nilai 4.096.Ini adalah batasan antarmuka terminal, khususnya mode kanonik ("dimasak") yang menyediakan editor garis yang sangat kasar (backspace, enter, Ctrl+ Dpada awal baris untuk akhir file). Itu terjadi sepenuhnya di luar proses yang membaca.
Anda dapat mengganti terminal ke mode mentah, yang menonaktifkan pemrosesan garis. Itu juga menonaktifkan Ctrl+ Ddan hal-hal lain, membuat beban tambahan pada program Anda.
Ini adalah batasan Unix kuno yang tidak pernah diperbaiki karena ada sedikit motivasi. Manusia tidak memasuki garis panjang seperti itu. Jika Anda memasukkan input dari suatu program, Anda akan mengarahkan input program Anda dari file atau pipa.
Misalnya, untuk menggunakan konten papan klip X, pipa dari
xsel
atauxclip
. Dalam kasus Anda:Hapus
-b
atau-selection clipboard
untuk menggunakan pilihan X (yang ditetapkan dengan menyorot dengan mouse) daripada clipboard.Di OSX, gunakan
pbpaste
untuk menempelkan konten clipboard (danpbcopy
untuk mengaturnya).Anda dapat mengakses papan klip X melalui SSH jika Anda mengaktifkan penerusan X11
ssh -X
(yang mungkin dilarang oleh beberapa server). Jika Anda hanya dapat menggunakanssh
tanpa penerusan X11, Anda dapat menggunakanscp
,sftp
atausshfs
untuk menyalin file.Jika menempel adalah satu-satunya solusi karena Anda tidak dapat meneruskan clipboard atau Anda tidak menempel tetapi misalnya memalsukan mengetik ke mesin virtual, pendekatan alternatif adalah menyandikan data menjadi sesuatu yang memiliki baris baru. Base64 sangat cocok untuk ini: ia mengubah data sewenang-wenang menjadi karakter yang dapat dicetak, dan mengabaikan spasi ketika mendekode. Pendekatan ini memiliki keunggulan tambahan yang mendukung data sewenang-wenang dalam input, bahkan mengontrol karakter yang akan ditafsirkan terminal ketika menempel. Dalam kasus Anda, Anda dapat menyandikan konten:
lalu decode:
sumber
xsel
dengan> 4k byte: github.com/kfish/xsel/issues/14Batas Anda menjalankan ke dalam adalah ukuran maksimum garis di mode input kanonik ,
MAX_CANON
.Dalam mode input kanonik, driver tty menyediakan layanan pengeditan garis dasar sehingga program userspace tidak perlu. Ini tidak memiliki hampir fitur sebanyak readline, tetapi mengenali beberapa karakter khusus yang dapat dikonfigurasi seperti menghapus (biasanya Backspace atau Hapus) dan membunuh (biasanya Ctrl-U).
Yang paling penting untuk pertanyaan Anda, input mode kanonik buffer hingga karakter end-of-line terlihat. Karena buffer ada dalam driver tty, dalam memori kernel, itu tidak terlalu besar.
Anda dapat mematikan mode kanonik dengan
stty cbreak
ataustty -icanon
, lalu lakukan tempel. Ini memiliki kerugian signifikan bahwa Anda tidak akan dapat mengirim EOF dengan Ctrl-D. Itu salah satu hal yang menjadi tanggung jawab mode kanonik. Anda masih dapat menghentikancat
dengan Ctrl-C karena karakter penghasil sinyal dikontrol oleh flag yang terpisah (stty raw
ataustty -isig
).Misteri bagi saya adalah mengapa, karena Anda sudah menunjukkan bahwa Anda tahu tentang
xclip
, Anda tidak hanya menggunakanxclip -o > file
bukannyacat
sumber
Jika kamu melakukan:
Dan kemudian jalankan demo yang disarankan di EDIT Anda, Anda akan melihat bilah foo di cetakan test.out . Baris disiplin terminal akan flush output nya ke pembacanya seperti membaca setiap khusus eol char dalam masukan Anda.
Terminal mode kanonik Linux - seperti yang dapat dikonfigurasi dengan
stty icanon
atau mungkin hanyastty sane
- menangani karakter input khusus berikut ...^D
^U
^H
(atau mungkin@
atau^?
pada beberapa sistem)Ketika iexten juga diatur - seperti
stty icanon iexten
atau, sekali lagi, mungkin hanyastty sane
, terminal Linux kanonik juga akan menangani ...^W
^R
^V
Karakter-karakter ini ditangani dengan menghapusnya dari aliran input - kecuali eol dan eol2 , yaitu - dan melakukan fungsi khusus yang terkait sebelum meneruskan aliran yang diproses ke pembaca - yang biasanya merupakan shell Anda, tetapi dapat berupa apa pun yang dilakukan oleh grup proses latar depan .
Karakter input khusus lainnya yang ditangani serupa tetapi dapat dikonfigurasikan secara independen dari pengaturan icanon apa pun termasuk set isig seperti
stty isig
dan mungkin juga termasuk dalam konfigurasi waras :^\
^Z
kill -CONT "$!"
atau hanyafg
dalam (set -m
) shell yang dikendalikan pekerjaan.^C
Dan set ixon - dikonfigurasi seperti
stty ixon
dan juga biasanya termasuk dalam konfigurasi waras :^S
^Q
Karakter khusus yang ditangani pada sistem non-Linux lainnya mungkin termasuk ...
^O
Dan mungkin...
^@
(artinya\0
atauNUL
)shl
shell-layer pada beberapa sistem.shl
yang multipleks ptys dan karenanya kompatibel dengan kontrol pekerjaan daripada perilaku swtch yang bergantung pada implementasi asli dapat secara bebas dimiliki dalamheirloom-toolchest
tool suite.Untuk gambaran yang lebih jelas tentang bagaimana dan mengapa (dan mungkin mengapa tidak) fungsi input ini ditangani berkonsultasi
man 3 termios
.Semua fungsi di atas dapat ditugaskan (atau dipindahkan) - jika ada - seperti
stty
function assigned-key
. Untuk menonaktifkan fungsi tunggal lakukan . Sebagai alternatif, karena berbagai upaya dengan penugasan untuk fungsi pengeditan baris yang disebutkan di atas dengan semua implementasi GNU, AST, atau heirloom tampaknya menunjukkan, Anda juga dapat sebagai penugasan NUL untuk fungsi apa pun tampaknya sama dengan mengaturnya agar tidak ditugaskan di linux saya. sistem.stty
function
^-
stty
stty
function
^@
Mungkin Anda memang melihat gema dari karakter-karakter ini ketika Anda mengetikkannya (karena kemungkinan dapat dikonfigurasi dengan [-] ctlecho ) , tetapi ini hanya penanda untuk menunjukkan di mana Anda melakukannya - program yang menerima input Anda tidak memiliki gagasan bahwa Anda ketik mereka (kecuali eol [2] , yaitu) dan hanya menerima salinan input Anda yang telah diterapkan disiplin disiplin efeknya.
Konsekuensi dari penanganan terminal terhadap berbagai fungsi pengeditan garis adalah bahwa ia harus memerlukan buffer input sampai batas tertentu agar dapat bertindak berdasarkan fungsi yang Anda tunjukkan kepadanya bahwa ia seharusnya - dan dengan demikian tidak mungkin ada pasokan input tanpa batas yang Anda bisa membunuh kapan saja . The garis buffer lebih tepatnya membunuh penyangga.
Jika Anda menetapkan karakter eol atau eol2 ke beberapa pembatas yang terjadi pada input - bahkan jika tidak ada baris baru atau karakter kembali, misalnya - maka Anda hanya akan dapat membunuh hingga titik yang terakhir terjadi dan buffer kill Anda akan meluas sejauh mungkin sampai selanjutnya - atau baris baru (atau kembali jika icrnl diatur dan igncr tidak) - terjadi pada input.
sumber
cat
akan menerima sejumlah karakter, seperti yang Anda saksikan dengan melakukan misalnyacat /dev/random > test.bin
(jangan lakukan itu kecuali Anda tahu cara menghentikannya :). Saya mencoba menyalin dan menempelkan file besar ke dalamnyacat > test.txt
. Semua baris berakhir di file apakah saya dibatalkan dengan Ctrl- catau Ctrl- d, tetapi dalam kasus sebelumnya tidak semua baris dicetak ke terminal . Saya percaya ini karenacat
buffer pencetakannya, menunggu buffer teks lengkap atau input langsung dari terminal sebelum setiap pencetakan.Pada sistem saya, saya pikir ukuran buffer adalah 4096 (2 ^ 12) byte: Buat file menggunakan 4095 byte
(printf '1234567890%.0s' {1..409} && printf 12345) > test.in
, muat ke buffer copy menggunakanxclip test.in
, mulaicat > test.out
, tempel menggunakan Shift- Insert, dan akhiri aliran dengan menekan Ctrl- d. Sekarang tambahkan byte menggunakanprintf '6' >> test.in
, dan aliran dicetak dua kali : Sekali dalamcat
output (semua 4096 byte), dan 4095 byte terakhir lagi pada shell setelah berakhir.sumber
Salah satu solusinya adalah menempelkannya ke editor yang mendukung garis panjang, misalnya vim.
Jika Anda menggunakan vim, pertama-tama masukkan mode tempel dengan
:paste
↵sebelum memasukkan mode sisipan dengan idan menempelkan teks.sumber