Bash'da SEKME ile ayrılmış dizeler nasıl yazdırılır?


9

Bir sekme ile ayrılmış iki dize yazdırmaya çalışıyorum. Denedim:

echo -e 'foo\tbar'
printf '%s\t%s\n' foo bar

Her ikisi de yazdırır:

foo     bar

İkisi arasındaki boşluk aslında 5 boşluktur (Putty'de fare ile çıktıyı seçmeye göre).

Ben de aynı sonucu ile komutu yazarken CTRL + V kullanarak ve SEKME tuşuna basmayı denedim.

Sekmeyi sekme olarak yazdırmaya zorlamanın doğru yolu nedir, böylece çıktıyı seçip sekmelerle başka bir yere kopyalayabilirim?

Ve ikincil soru: bash neden sekmeleri boşluklara genişletiyor?

Güncelleme : Görünüşe göre, bu bir Macun sorunu: /superuser/656838/how-to-make-putty-display-tabs-within-a-file-instead-of-changing-them-to -spaces



Neden kaçmasın? printf '%s\\t%s\n' foo bar
Valentin Bajrami

@steeldriver Teşekkürler ihtiyacım olana çok benziyor, ama sonuçta bir çözüm yok ...
Asu

1
@Valentin Bu çıktılar foo\tbar...
wjandrea

1
Terminalinizle ilgili bir sorununuz olduğunu zaten biliyor olmanıza rağmen: Bash tek başına $'\t'tabülatör olarak yorumluyor . Böylece her zaman böyle dizeleri birleştirebilirsiniz - örneğin atama olarak: v='This is'$'\t''a test'Ve kelimenin tam anlamıyla yazdırın, örneğinprintf '%s' "$v"
rexkogitans

Yanıtlar:


9

İlkkachu'nun dediği gibi, bu bash ile ilgili bir sorun değil, sekmeleri çıktıdaki alanlara dönüştüren terminal emülatörü ile ilgili.

Farklı terminalleri kontrol etmek, macun, xterm ve konsole sekmeleri boşluklara dönüştürürken urxvt ve gnome-terminali dönüştürmez. Yani, başka bir çözüm terminalleri değiştirmek.


3
Ayrıca çalıştırdıktan sonra tty sürücüsü tarafından da yapılabilir stty tab3.
Stéphane Chazelas

14

ikisi arasındaki boşluk aslında 5 boşluktur.

Hayır değil. echoVeya çıktısında değil printf.

$ echo -e 'foo\tbar' | od -c
0000000   f   o   o  \t   b   a   r  \n
0000010

Sekmeyi sekme olarak yazdırmaya zorlamanın doğru yolu nedir, böylece çıktıyı seçip sekmelerle başka bir yere kopyalayabilirim?

Bu farklı bir konudur. Kabuk ile ilgili değil, sekmeleri çıktıdaki boşluklara dönüştüren terminal emülatörü. Çoğu, ama hepsi bunu yapmıyor.

Çıktıyı sekmeli bir dosyaya yeniden yönlendirmek ve oradan kopyalamak veya unexpandçıktıda boşlukları sekmelere dönüştürmek için kullanmak daha kolay olabilir . (Yine de hangi boşlukun sekmeler olduğunu bilmiyor olsa da ve mümkünse sekmelere dönüştürecektir.) Bu elbette çıktı ile ne yapmanız gerektiğine bağlı olacaktır.


Demek istediğim, çıktıyı seçmeye çalıştığımda 5 boşluk olarak işlem görüyor. Komut çıkışının içeriğini doğrulamak için 'od -c' için teşekkürler.
Asu

1
@ Sanırım bunu anlıyor. Onun çözümü, diğer yollarla çıkışı elde etmektir, çünkü terminal emülatörünün pencerede seçtiğinizde sekmeleri sekmeler olarak bırakması garanti edilmez. Ancak, ben sadece kontrol ve macun, xterm ve konsole sekmeleri boşluklara dönüştürürken, urxvt ve gnome-terminali değil. Yani, başka bir çözüm terminalleri değiştirmek.
JoL

@JoL Evet, bu sadece bir dakika önce geldiğim sonuç ve sanırım biri bunu böyle yayınlamayı umarsa kabul edilen cevap olur ...
Asu

1
@Asu, evet, sadece sorunu elle çözmeyi düşündüm. Bunu yapmak can sıkıcı olurdu, ama sonra kopya sekmelerini destekleyen terminal emülatörlerinin olduğunu fark etmediğimi itiraf ediyorum. Birine geçmek elbette çok daha iyi bir çözüm olacaktır!
ilkkachu

4

In printf '%s\t%s\n' foo bar, printfçıktı alır foo<TAB>bar<LF>.

f, o, b, aVe rtek genişlikli bir grafik karakterler.

Bu karakterleri aldıktan sonra, terminal karşılık gelen bir glif gösterecek ve ekranın sağ kenarına (orijinal tele-daktilolardaki kağıt) ulaşılmadıkça imleci bir sütun sağa hareket ettirecektir, bu durumda bir satır besleyebilir ve ekranın sol kenarına dönün (sarın) veya sadece terminale ve nasıl yapılandırıldığına bağlı olarak karakteri atın.

<Tab>ve <LF>iki kontrol karakteridir. <LF>(diğer adıyla newline) Unix metnindeki satır sınırlayıcıdır, ancak terminaller için yalnızca bir satır besler (imleci bir konum aşağı hareket ettir). Böylece çekirdekteki terminal sürücüsü onu <CR>(ekranın sol kenarına dön), <LF>(imleç aşağı) ( stty onlcrgenellikle varsayılan olarak açık ) olarak çevirir .

<Tab> terminale imleci bir sonraki sekme durağına (çoğu terminalde varsayılan olarak 8 konum aralıklıdır, ancak boşluğu boşluklarla doldurmadan da ayarlanabilir) yapılandırılmasını söyler.

Bu karakterler, imleç boş bir satırın başlangıcındayken sekme durağı sekme durağı olan bir terminale gönderilirse, bunun sonucu oluşur:

foo     bar

ekranda o satırda yazdırılır. Eğer imleç içeren bir satırda üçüncü konumdayken gönderilirlerse xxxxyyyyzzzz, bunun sonucunda şunlar olur:

xxfooyyybarz

Tablolamayı desteklemeyen terminallerde, terminal sürücüsü bu sekmeleri boşluk dizilerine çevirecek şekilde yapılandırılabilir. ( stty tab3).

Orijinal tele-daktilolardaki SPC karakteri imleci sağa, backspace ( \b) ise sola hareket ettirir. Şimdi modern terminallerde, SPC sağa hareket eder ve ayrıca siler (beklediğiniz gibi bir boşluk karakteri yazar). Yani kolye ucu \bASCII'den daha yeni bir şey olmalıydı. En modern terminallerinden günü, aslında karakterlerin bir sırası bulunmaktadır: <Esc>, [, C.

nKarakterleri sola, sağa, yukarı, aşağı veya ekranda herhangi bir konuma taşımak için daha fazla kaçış dizisi vardır . Ekranın satırlarını veya bölgelerini vb. Silmek (boşla doldurmak) için başka kaçış dizileri vardır.

Bu diziler tipik haliyle gibi görsel uygulama tarafından kullanılan vi, lynx, mutt, dialogmetin ekranında rastgele konumlarda yazılı olduğu.

Şimdi, tüm X11 terminal emülatörleri ve GNU gibi birkaç X11 olmayan diğerleri screen, kopyala yapıştırmak için ekranın alanlarını seçmenizi sağlar. viEditörde gördüklerinizin bir bölümünü seçtiğinizde , bu çıktıyı üretmek için kullanılmış olan tüm çıkış dizilerini kopyalamak istemezsiniz. Orada gördüğünüz metni seçmek istiyorsunuz.

Örneğin;

printf 'abC\rAC\bB\t\e[C\b\bD\n'

Girdiğiniz bir editör oturumu simüle Hangi abCyerine, başına dönebilsem abile AC, Cile Bgirmek, sonra sola, sonra sağa, sonra bir sonraki sekme durağına, iki sütun Bir sütunu daha hamle D.

Anlıyorsun:

ABC    D

Yani, ABC4 sütunlu bir boşluk ve D.

İçinde fare ile o seçerseniz xtermveya puttybunlar seçiminde saklayacak ABC, 4 uzay karakterleri ve Ddeğil abC<CR>AC<BS>B<Tab><Esc>[C<BS><BS>D.

Seçimde sonuçlanan printf, hem terminal sürücüsü hem de terminal emülatörü tarafından gönderilen ancak sonradan işlenen şeydir .

Dönüşümün diğer çeşitleri için bkz <U+0065><U+0301>( ebir birleşme vurgu işareti elde edilmiş) değiştirildi <U+00E9>( éönceden oluşan formu) ile xterm.

Ya da echo abcbu durum ABCa stty olcuc. Sonrasında terminale göndermeden önce terminal sürücüsü tarafından çevrilir .

Şimdi <Tab>, böyle <LF>aslında bazen (aynı zamanda metin dosyaları bulunan bu birkaç denetim karakterlerinden biri olan <CR>bazen MSDOS metin dosyaları ve <FF>sayfa sonu için).

Bu nedenle, bazı terminal emülatörleri, onları korumak için kopyala-yapıştır arabelleklerine mümkün olduğunda kopyalamayı seçer (genellikle <CR>ne olur ne de <LF>olsa).

Örneğin, gibi VTE tabanlı terminallerde gnome-terminal, printf 'a\tb\n'boş bir satırın çıkışını seçtiğinizde , gnome-terminalaslında 7 boşluk ve a\tbyerine X11 seçiminde saklandığını görebilirsiniz .ab

Ancak çıkışı için printf 'a\t\bb\n'onu sakladığı a, 6 alanları ve bve için printf 'a\r\tb\n', a7 boşluk ve b.

Terminallerin gerçek girişi kopyalamaya çalışacağı başka durumlar da vardır; örneğin printf 'a \nb\n', görünmez sondaki alanın korunacağı yerde çalıştırdıktan sonra iki satır seçtiğinizde . Ya da iki satır seçerken, iki satır sağ kenar boşluğuna sarılarak bir LF karakteri içermez.

Şimdi, çıktısını printfCLIPBOARD seçimine X11kaydetmek istiyorsanız, en iyisi doğrudan şu şekilde yapmaktır:

printf 'foo\tbar\n' | xclip -sel c

Not o yapıştırdığınızda olduğu xtermdiğer birçok terminaller veya xtermaslında değiştirir \nile \ro karakter çünkü xtermsen bastığınızda gönderir Enter(ve terminal sürücü geri çevirmek olabilir \n).


Bu çok anlayışlı, teşekkürler. Ben xclip çözüm denedim ve çalışıyor. Ama aklımdaki şeyi tam olarak yapmıyor ve X11 gerektiriyor. Belki bu bir noktada kullanışlı olacak, teşekkürler!
Asu

@Asu, Unix X11gibi xtermveya puttyUnix gibi terminal öykünücülerinde kopyala-yapıştır seçimini yapan şeydir . Diğer terminal emülatörlerinin kendi kopyala yapıştırma mekanizması ve GNU ekranındaki readbuf ve registerkomutları gibi keyfi içeriği depolamanın yolları olabilir .
Stéphane Chazelas
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.