Bir terminalde yeni çizgiler olmadan 4k'dan fazla girdi nasıl okunur?


25

Bu yüzden panodaki YENİ HATLAR OLMADAN bir sürü veri var (bir satırda büyük bir SVG dosyası var). gittim

$ cat >file.svg

daha sonra (Gnome Terminalinde) yapıştırmaya çalıştı, ancak yalnızca ilk 4kB karakter kabul edildi.

Bunun bir okuma satırı özelliği / sınırlaması olduğunu varsayıyorum.

STDIN'den okumanın bu sorunu önleyebilecek bir yolu var mı?

DÜZENLE

Test durumu: Bir demo dosyası oluşturun. Bu, "4k" = "sembollerini, ardından" foo bar "ı izleyecektir.

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

Onu panoya kopyala

xclip test.in

(eklemek için orta tıklamak istiyorsanız) veya

xclip -selection clipboard test.in

(geçmişine yapıştırmak için Ctrl-Shift-Insert kullanmak istiyorsanız)

Ardından cat >test.out, hangisi olursa olsun yapıştırın. Akışı sonlandırmak için Ctrl-D tuşlarına basın. cat test.out- "Foo bar" görüyor musun?

Yaptığımda (Ubuntu 12.04, Gnome Terminal, zsh) yapıştırdığımda sadece görüyorum =ve göremiyorum foo bar. Teftiş ettiğimde aynı test.out.


SVG dosyanızın tamamen panosunuza okuduğundan emin misiniz?
lgeorget

Asıl problemin ne? Pano içeriğini bir dosyaya nasıl saklayabilirim? Eğer öyleyse, terminale yapıştırmanın dışında başka bir yol vardır.
lgeorget

senin durumunda ne kadar N var? Ben 2kB xml veri (LF dahil) hiçbir sorun ile denedim.
fduff

1
@artfulrobot Bir ön plan işlemi doğrudan tty / pty ile etkileşime girer. Kabuk dahil değildir. Bunu görebilirsiniz çünkü programlarda okuma satırı veya başka bir giriş kütüphanesi kullanmıyorlarsa okuma satırı özellikleri (düzenleme / atlama komutları, tarih, ...) bulunmaz.
jofel

1
Bu bir okuma satırı sınırlaması değil - okuma satırı ve bash burada yer almıyor. Terminal arayüzünün bir sınırlaması.
Gilles 'SO- kötülük'

Yanıtlar:


22

Kaynağı doğru anlarsam, Linux altında, bir terminalde bir kerede okunabilecek maksimum karakter sayısı N_TTY_BUF_SIZEçekirdek kaynağında belirlenir. Değeri 4096.

Bu, terminal arayüzünün bir sınırlamasıdır, özellikle aşırı derecede kaba bir çizgi editörü sağlayan kanonik (“pişmiş”) moddur ( dosya sonu için bir satırın başında geri al, gir, Ctrl+ D). Tamamen okuma sürecinin dışında gerçekleşir.

Terminali, satır işlemeyi devre dışı bırakan ham moda geçebilirsiniz. Ayrıca , programınıza ek bir yük getirerek, Ctrl+ Dve diğer tatlıları devre dışı bırakır .

Bu hiç bir zaman düzeltilmemiş eski bir Unix sınırlamasıdır çünkü çok az motivasyon vardır. İnsanlar bu kadar uzun çizgilere girmezler. Bir programdan girdiler besliyorsanız, programınızın girişini bir dosyadan veya bir kanaldan yönlendirirsiniz.

Örneğin, X panosunun içeriğini kullanmak için, piponun xselveya konumundan kullanılması xclip. Senin durumunda:

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

Panodan ziyade X seçimini (fareyle vurgulanarak ayarlanır) kaldırın -bveya -selection clipboardkullanın.

OSX'te pbpastepano içeriğini yapıştırmak (ve pbcopyayarlamak için) kullanın.

X11 iletmeyi etkinleştirirseniz ssh -X(bazı sunucular yasaklayabilir) , X panosuna SSH üzerinden erişebilirsiniz . Yalnızca sshX11 iletmeden kullanabilirsiniz scp, bir dosyayı kopyalamak için kullanabilir sftpveya kullanabilirsiniz sshfs.

Yapıştırmanın tek yolu, yapıştırmayı iletemediğiniz veya yapıştırmadığınız, ancak örneğin bir sanal makineye yazarak taklit etmekse, alternatif bir yaklaşım, verileri yeni satırlara sahip bir şeye kodlamaktır. Base64 bunun için çok uygundur: isteğe bağlı verileri yazdırılabilir karakterlere dönüştürür ve kod çözme sırasında boşlukları yok sayar. Bu yaklaşım, girişteki keyfi verileri desteklemesi, hatta terminalin yapıştırırken yorumlayacağı karakterleri kontrol etmesi için ek bir avantaja sahiptir. Senin durumunda, içeriği kodlayabilirsin:

xsel -b | base64 | xsel -b

sonra kodunu çözün:

base64 -d
 Paste
Ctrl+D

xsel> 4k bytes ile kullanıldığında çok kötü bir veri bozulma hatası olduğuna dikkat edin
Patrick

14

Eğer yaşamaya devam edip sınır içinde bir satırın en büyük boyut olan kurallı girdi kipinde , MAX_CANON.

Kurallı giriş modunda, tty sürücüsü, temel alan düzenleme hizmetlerini sağlar, böylece kullanıcı alanı programının gerekmesine gerek kalmaz. Neredeyse okuma satırı kadar çok özelliğe sahip değildir, ancak silme (genellikle Geri veya Sil) ve öldürme (genellikle Ctrl-U) gibi birkaç yapılandırılabilir özel karakter tanır.

Sorunuz için en önemlisi, kanonik mod, satır sonu karakteri görünene kadar girdiyi tamponlar. Arabellek tty sürücüsünde, çekirdek bellekte olduğundan, çok büyük değil.

Kurallı modu stty cbreakveya ile kapatabilir stty -icanonve ardından yapıştırmanızı yapabilirsiniz. Bu, Ctrl-D ile bir EOF gönderemeyeceğiniz gibi önemli bir dezavantaja sahiptir. Bu, kanonik modun sorumlu olduğu şeylerden bir diğeridir. catSinyal üreten karakterler ayrı bir bayrak ( stty rawveya stty -isig) tarafından kontrol edildiğinden , hala Ctrl-C ile sonlandırabilirsiniz .

Bana sır neden, zaten bilmen göstermiştir beri olduğu xclip, sadece kullanmayın xclip -o > fileyerinecat


1
Gizem kolayca çözülebilir: Artfulrobot'un uzaktaki bir bilgisayardaki bir dosyayı panodaki verilerle hızla doldurmak istediği anlaşılıyor. Uzak kabukta, normal olarak xclip ile yerel panoya doğrudan erişim yoktur.
jofel

3
Ah, güzel eski yükleme yapıştırma. Bunlardan birini yapmak zorunda kalsaydım ve düz metin olmasaydı, tty sürücüsünü geçmesi için ikna etmeye çalışmak yerine, onu kod olarak kullanırdım. Muazzam çizgileri olan düz metin de bu şekilde kullanılabilir.

2

Yaparsan:

stty eol =

Ve sonra önerilen demo çalıştırmak EDIT'e , göreceksiniz foo bar baskısına test.out . Terminalin hat disiplini, girişinizdeki her özel char ok karakterini okurken çıktısını okuyucusuna aktaracaktır .

Bir Linux kanonik-mod terminali - ile stty icanonveya muhtemelen sadece stty sane- yapılandırılabildiği gibi aşağıdaki özel giriş karakterlerini işler ...

  • eof
    • varsayılan: ^D
    • Bir giriş hattını sonlandırır ve okuyucunun çıkışını temizler. Girdiden kaldırıldığından, bir satırdaki tek karakter olarak girildiyse , okuyucuya boş bir okuma - veya dosyanın sonu - geçirilir .
  • eol
    • varsayılan: atanmamış
    • Ayrıca bir giriş satırını sonlandırır, ancak girişden kaldırılmaz.
  • öldürmek
    • varsayılan: ^U
    • Tüm tamponlanmış girişi siler.
  • silme
    • varsayılan: ^H (veya muhtemelen @veya ^?bazı sistemlerde)
    • Tamponlu son giriş karakterini siler.

Ne zaman IEXTEN da ayarlanır - benzeri stty icanon iextenveya yine muhtemelen sadece stty sanebir kanonik Linux terminali de idare edecek ...

  • EOL2
    • varsayılan: atanmamış
    • Ayrıca , aynı zamanda , bir giriş hattı sona erdirir, ve aynı zamanda giriş kaldırılmaz.
  • WERASE
    • varsayılan: ^W
    • Tamponlu son giriş kelimesini siler .
  • rprnt
    • varsayılan: ^R
    • Tüm arabelleğe alınmış girişi yeniden yazdırır.
  • bit LNEXT
    • varsayılan: ^V
    • Satır disiplininin hemen takip eden giriş karakteriyle ilgili olduğu her türlü özel önemi kaldırır.

Bu karakterler giriş akımından çıkarılarak - eol ve eol2 hariç - ve işlenmiş akışı okuyucuya aktarmadan önce ilgili özel işlevi yerine getirerek ele alınır - bu genellikle sizin kabuğunuzdur, ancak ön plan işlem grubu ne olursa olsun .

Benzer işlenir ancak herhangi bir bağımsız yapılandırılabilir Diğer özel giriş karakterler ICANON ayarı dahil isig set - gibi set stty isigbir ve muhtemelen de dahil aklı başında yapılandırması:

  • çıkmak
    • varsayılan: ^\
    • Tüm tamponlanmış girişi temizler ( noflsh ayarlanmadıysa) ve SIGQUIT'i ön plan işlem grubuna gönderir - büyük olasılıkla bir çekirdek dökümü oluşturur.
  • susp
    • varsayılan: ^Z
    • Tüm tamponlanmış girişi temizler ( noflsh ayarlanmadıysa) ve SIGTSTP'yi ön plan işlem grubuna gönderir. Süspansiyon işlem grubu muhtemelen herhangi biri ile devam edilebilir kill -CONT "$!"veya fgbir bölgesindeki ( set -m) iş kontrollü kabuk.
  • geçişsiz
    • varsayılan: ^C
    • Tüm tamponlanmış girişi temizler ( noflsh ayarlanmadıysa) ve SIGINT'i ön plan işlem grubuna gönderir.

Ve ixon set - benzer bir yapıya sahip stty ixonve aynı zamanda bir aklı başında config de var:

  • durdurmak
    • varsayılan: ^S
    • Ya kadar okuyucuya tüm çıkışını durdurur başlangıç girişi okumak veya - zaman ixany da ayarlanır - en az bir adet daha fazla karakter okunur.
  • başla
    • varsayılan: ^Q
    • Daha önce birlikte durduysa Yeniden Hizmete çıkış durağı .
  • Hem durdurma hem de başlatma işlemi işlendiğinde girişten kaldırılır, ancak ixany ayarlandığında girilen herhangi bir karakter nedeniyle çıkış yeniden başlatılırsa , o karakter kaldırılmaz.

Diğer Linux dışı sistemlerde işlenen özel karakterler şunları içerebilir ...

  • floş
    • varsayılan: ^O
    • Tamponlu girişin atılmasını ve temizlenmesini değiştirir ve girişten kaldırılır.
  • DSUSP
    • varsayılan: atanmamış
    • Arabelleğe alınan tüm girdileri yalnızca okuyucu atanan özel giriş karakterini okuduğunda temizler ve ardından SIGTSTP gönderir.

Ve muhtemelen ...

  • swtch
    • varsayılan ^@ (anlam \0veya NUL)
    • Ön plan kabuk katmanlarını değiştirir. İle kullanım için shl kabuk tabakalar bazı sistemlerde uygulaması.
    • Bir uygulama shlmultiplexes PTY bu ve iş kontrolü yerine orijinal uygulanması en ile de uyumludur olan swtch bağımlı davranış serbestçe bulunabilmektedir heirloom-toolchestaracı paketi.

Bu giriş fonksiyonlarının nasıl ve niçin (ve belki de niçin olmasın) daha net bir resmi için danışın man 3 termios.

Yukarıdaki fonksiyonların tümü, uygun olduğunda - benzeri şekilde atanabilir (veya yeniden atanabilir)sttyfunction assigned-key . Herhangi bir tek işlevi devre dışı bırakmak için yapın . Alternatif olarak, yukarıda bahsedilen çizgi düzenleme işlevlerinden herhangi biri için yapılan tüm GNU, AST veya yadigarı uygulamaları için yapılan çeşitli girişimlerden anlaşılacağı gibi, herhangi bir işleve NUL ataması olarak, linux'uma atanmamış olarak ayarlamaya eşit gibi görünebilir. sistemi.sttyfunction^-sttysttyfunction^@

Muhtemelen bunları yazarken bu karakterlerin bir yankılanmasını görüyorsunuz (muhtemelen w / [-] ctlecho ile yapılandırılabilir ) , ancak bu yalnızca yaptığınız yeri gösterecek bir işaretçidir - girişinizi alan program sizin hiçbir fikriniz yok onları daktilo (hariç EOL [2] olduğunu,) ve çizgi disiplin bunların etkilerini başvuruda bulunduğu için giriş yalnızca bir kopyasını alır.

Terminalin çeşitli çizgi düzenleme işlevlerini kullanmasının bir sonucu, belirtmesi gereken işlevleri yerine getirmek için girdiyi bir dereceye kadar tamponlaması gerekmesi gerektiğidir - ve bu nedenle sınırsız bir giriş kaynağı olamaz. İstediğin zaman öldürebilirsin . Çizgi tampon daha kesin olduğunu öldürme tampon.

Ayarlarsanız eol veya EOL2 ne bir satır veya bir dönüş karakteri, örneğin olsa bile - - o zaman sadece mümkün olacak girişinde meydana bazı sınırlayıcı karakterleri öldürmek son gerçekleştiği noktaya kadar ve öldürmek tampon girişte , bunların sonuna kadar uzayacaktır - veya yeni bir satır (veya icrnl ayarlanmış ve igncr ayarlanmamışsa döndür ) -.


1

catÖrneğin, bunu yaparken şahit olabileceğiniz kadar çok sayıda karakter kabul edecektir cat /dev/random > test.bin(nasıl durduracağınızı bilmiyorsanız bunu yapmayın :). Ben kopyalayıp yapıştırarak çalıştı büyük bir dosya içine cat > test.txt. Tüm satırlar Ctrl- cveya Ctrl- ile iptal edip etmeme izin verdi d, ancak önceki durumda tüm satırlar terminale yazdırılmadı . Bunun cat, baskıyı tamponlamadan, her baskıdan önce terminalden tam bir metin tamponu veya doğrudan giriş beklemesinden kaynaklandığına inanıyorum .

Sistemimde, arabellek boyutunun 4096 (2 ^ 12) bayt olduğunu düşünüyorum: 4095 baytlık bir dosya oluşturun (printf '1234567890%.0s' {1..409} && printf 12345) > test.in, kullanarak kopya arabelleğe yükleyin xclip test.in, - cat > test.outkullanarak başlamak , yapıştırın - kullanarak yapıştırın ve - düğmesine basarak akışı sonlandırın . Şimdi kullanarak bir bayt ekleyin ; akış iki kez yazdırılır : Çıktıda bir kez (tümü 4096 bayt) ve sonlandırıldıktan sonra kabukta son 4095 bayt tekrar .ShiftInsertCtrldprintf '6' >> test.incat


+1 Benim durumumda, kullanılan panoya da bağlıydı. Seçim arabelleğini kullandıysam (orta tıklama yapıştırması) sadece test verilerimin ilk 4542 satırını gördüm (ama hepsi oluşturulan dosyada bitti) ama X panoyu kullanarak (Ctrl + C / Ctrl + V) gördüm. hepsini. Her iki durumda da, tüm veriler sonuçlanan dosyaya basılmıştır, ancak ilkinde terminalde yalnızca kısmi veriler gösterilmiştir.
terdon

1
Aynı davranışı alamıyorum. Düzenlenmiş soruya bakın
artfulrobot

0

Çözümlerden biri, örneğin vim gibi uzun satırları destekleyen bir düzenleyiciye yapıştırmaktır.

Vim kullanıyorsanız, :pasteönce imetin ekleme ve yapıştırma işlemine başlamadan önce önce yapıştırma moduna girin .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.