TAB
Karakteri bir terminal¹ gönderilen bir sonraki sekme durağına terminalin imleci hamle yapar bir kontrol karakteridir. Varsayılan olarak, çoğu terminalde sekme durakları 8 sütun aralıklıdır, ancak bu yapılandırılabilir.
Ayrıca, düzensiz aralıklarla sekme durakları da olabilir:
$ tabs 3 9 11; printf '\tx\ty\tz\n'
x y z
Yalnızca terminal, bir SEKME'nin sağdaki kaç sütunu imleci hareket ettireceğini bilir.
Sekme gönderilmeden önce ve sonra terminalden imleç konumunu sorgulayarak bu bilgileri alabilirsiniz.
Belirli bir satır için bu hesaplamayı el ile yapmak ve bu satırın ekranın ilk sütununa yazdırıldığını varsayarsanız, şunları yapmanız gerekir:
- sekme duraklarının nerede olduğunu bilir²
- her karakterin ekran genişliğini bilir
- ekranın genişliğini bilir
\r
(imleci ilk sütuna \b
taşır ) veya imleci geri taşır ... gibi diğer kontrol karakterlerini işlemek isteyip istemediğinize karar verin.
Sekme duraklarının her 8 sütunda olduğunu, satırın ekrana sığdığını ve terminalinizin düzgün bir şekilde görüntüleyemeyeceği başka kontrol karakterleri veya karakterleri (veya karakter olmayan) olmadığını varsayarsanız basitleştirilebilir.
GNU ile wc
, eğer hat şurada depolanmışsa $line
:
width=$(printf %s "$line" | wc -L)
width_without_tabs=$(printf %s "$line" | tr -d '\t' | wc -L)
width_of_tabs=$((width - width_without_tabs))
wc -L
girişindeki en geniş çizginin genişliğini verir. Bunu wcwidth(3)
karakterlerin genişliğini belirlemek için ve sekme duraklarının her 8 sütunda olduğunu varsayarak yapar.
GNU olmayan sistemler ve aynı varsayımlarla, @ Kusalananda'nın yaklaşımına bakınız . Sekme duraklarını belirtmenize izin verdiği için daha da iyidir, ancak expand
giriş çok baytlı karakterler veya 0 genişlikli (karakterleri birleştirmek gibi) veya çift genişlikli karakterler içerdiğinde maalesef şu anda GNU (en azından) ile çalışmaz .
Ancak bunu yaparsanız stty tab3
, tty cihaz hattı disiplinin sekme işlemeyi devralacağını (TAB'ı imlecin terminale göndermeden önce nerede olabileceğine dair kendi fikrine dayanarak boşluklara dönüştürecek) ve sekmenin her 8 sütunda durduğunu unutmayın. Linux'ta test yaparken, CR, LF ve BS karakterlerinin yanı sıra çok baytlı UTF-8 karakterlerini (sağlandığı da iutf8
açıktır) düzgün ele alıyor gibi görünüyor, ancak hepsi bu. Diğer tüm kontrol dışı karakterlerin (sıfır genişlik, çift genişlikli karakterler dahil) 1 genişliğine sahip olduğunu varsayar (açıkçası) kaçış dizilerini işlemez, düzgün bir şekilde sarılmaz ... Bu muhtemelen terminaller için tasarlanmıştır. sekme işleme yapamıyor.
Her durumda, tty satır disiplininin imlecin nerede olduğunu bilmesi gerekir ve yukarıdaki buluşsal yöntemleri kullanır, çünkü icanon
satır düzenleyiciyi kullanırken (bunun gibi uygulamalar için metin girdiğinizde cat
kendi satır düzenleyicilerini uygulamadığınızda olduğu gibi ), basın TabBackspace, çizgi disiplin göndermek için kaç BS karakter bilmesi gereken silme gösterilecek yeri Sekme karakteri. Sekmenin durduğu yeri değiştirirseniz (ile olduğu gibi tabs 12
), Sekmelerin düzgün bir şekilde silinmediğini fark edersiniz. Tuşuna basmadan önce çift genişlikli karakterler girerseniz aynı olur TabBackspace.
² Bunun için sekme karakterleri gönderebilir ve her birinin ardından imleç konumunu sorgulayabilirsiniz. Gibi bir şey:
tabs=$(
saved_settings=$(stty -g)
stty -icanon min 1 time 0 -echo
gawk -vRS=R -F';' -vORS= < /dev/tty '
function out(s) {print s > "/dev/tty"; fflush("/dev/tty")}
BEGIN{out("\r\t\33[6n")}
$NF <= prev {out("\r"); exit}
{print sep ($NF - 1); sep=","; prev = $NF; out("\t\33[6n")}'
stty "$saved_settings"
)
Daha sonra bunu expand -t "$tabs"
@ Kusalananda'nın çözümünü kullanarak kullanabilirsiniz .
x
aramadan önce boşlukları başka bir tek genişlikli karakterle (gibi ) değiştirmek istersinizexpand
, başlangıçta girişte bulunan boşlukları da saymış olursunuz.