Bash istemi için bir işlevde yazdırılmayan karakterlerden kaçış


22

Bash Prompt'ta (PS1 değişkeni), istemde potansiyel olarak metin eklemek için bir işlev çağırıyorum: export PS1="\u@\h \$(my_function) \$ "

Bununla birlikte, bilgi istemindeki fonksiyon, fonksiyonun çıkışına bağlı olarak değişen ANSI renk kodlarını içerir (bazen kırmızı, bazen yeşil). \[PS1 değişkenine " " eklenmesi , bu kodları yazdırılmayan olarak çıkarmalıdır, ancak echoişlevde bir giriş yaparsam , " \[" komut istemine tam olarak basılır.

Bu ANSI renk kodlarını bir bash komut isteminde kullanmak üzere bir fonksiyondan nasıl uzaklaştırabilirim?

Yanıtlar:


34

Taleb kütüphanesi kabul \001ve \002(ASCII SOH ve STX olmayan yazdırılabilir metin sınırlayıcı olarak). Bunlar, readline kullanan herhangi bir uygulamada da çalışır .

Gönderen lib/readline/display.c:243içinde bash kaynak kodu:

243 /* Current implementation:
244         \001 (^A) start non-visible characters
245         \002 (^B) end non-visible characters
246    all characters except \001 and \002 (following a \001) are copied to
247    the returned string; all characters except those between \001 and
248    \002 are assumed to be `visible'. */

Bash 'e özgü \[ve \]aslında çevrilir \001ve \002en y.tab.c:7640.


Not: kullanıyorsanız bash 'ın printfveya echo -eve metin varsa \001veya \002hemen bir sayı önce bir hit olacak bash sekizlik kaçar işlerken o tek basamaklı çok fazla yemeye neden olan hata - olduğunu, \00142sekizlik olarak yorumlanacaktır 014 (ardından ASCII "2"), doğru sekizlik 01 (ardından ASCII "42") yerine. Bu nedenle, onaltılık sürümleri \x01ve \x02yerine kullanın.


Bu yapar! echo -e "\001\e[31m\002RED"beklendiği gibi çalışır. Teşekkürler!
MidnightLightning

Bir cevabı tekrar gönderdiğim için özür dilerim, ancak kısa çizgi / ash / sh'in karşılığı nedir?
Hosh Sadiq

@Hosh Eğer readline kullanıyorlarsa \001ve \002çalışacaklardır. Aksi halde emin değilim. Örneğin Dash kesinlikle readline kullanmıyor .
wjandrea

1

İşte güzel bir tam cevap. 001'in nereye gitmesi gerektiğine karar vermek için daha fazla kazma yapmak zorunda kaldım. Bu yardımcı olur umarım.

# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)

PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'

alias branchname="git branch 2>/dev/null | grep '*' | sed 's/* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/'"

GIT_STATUS='$(branchname)'

PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "

Burada kurma biçimim, git şube parantezleri yalnızca bir git dalındaysanız görünür, aksi takdirde boştur.


0

Göre grawity cevabı , şu ANSI kontrolü ASCII dizileri çevrelerler SOH( ^A) ve STX( ^Beşdeğerdir) \[ve \]sırasıyla:

function readline_ANSI_escape() {
  if [[ $# -ge 1 ]]; then
    echo "$*"
  else
    cat  # Read string from STDIN
  fi | \
  perl -pe 's/(?:(?<!\x1)|(?<!\\\[))(\x1b\[[0-9;]*[mG])(?!\x2|\\\])/\x1\1\x2/g'
}

Gibi kullanın:

$ echo $'\e[0;1;31mRED' | readline_ANSI_escape

Veya:

$ readline_ANSI_escape "$string"

Bir bonus olarak, işlevi birden çok kez çalıştırmak, hali hazırda kaçmış olan kontrol kodlarından tekrar kaçmayacaktır.


-2

Onları istemi kullanmak istiyorsanız, o zaman yapmanız gerekir \[. Fakat onu bir yankıda kullanmak istiyorsanız, kullanmak zorundasınız \033[.


Hmmm ... \ 033 [ANSI komutundan önce ("\ e [31m") ve \ 033] eklendikten sonra komut satırında bir sonraki yazdırılan karakter yazdırılmıyor gibi görünüyor.
MidnightLightning

1
Bundan sonra \ 033] yapmak istemezsin. \ 033 [31m rengi başlatır, bundan sonra geri koymak için \ 033 [0m
Wuffers
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.