Bash: Çıkış durumunu istemde görüntüle:


11
GREEN="\e[1;32m"
RED="\e[1;31m"
NONE="\e[m"

get_exit_status(){
   es=$?
   if [ $es -eq 0 ]
   then
       echo -e "${GREEN}${es}${NONE}"
   else
       echo -e "${RED}${es}${NONE}"
   fi
}

get_path(){
    #dummy function
    echo "PATH"
}

PROMPT_COMMAND='exitStatus=$(get_exit_status)'

Aşağıdaki bana doğru exitStatus verir, ancak renk değişkenleri genişletilmez:

PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '

Ancak, aşağıdaki renk bana renk veriyor ancak çıkış durumu güncellenmiyor:

PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "

Bunu yapmanın doğru yolu nedir? ExitStatus ve renklerin her ikisinin de çalışması için bunu nasıl düzeltebilirim?

Yanıtlar:


8

Gilles ana probleminizi belirledi, ama ben farklı bir şekilde açıklamayı denemek istedim.

Bash, özel bilgi isteminin kaçışlarını yalnızca bilgi istemindeki değişkenleri genişletmeden önce yorumlar . Bu \e, doğrudan çalışmasına rağmen bilgi isteminden genişletilen bir değişkende kullanılmasının işe yaramayacağı anlamına gelir PS1.

Örneğin, bu beklendiği gibi çalışır ve kırmızı metin verir:

PS1='\e[1;31m this is in red '

Ama bu değil, sadece bilgi \eistemine neden olur:

RED='\e[1;31m'
PS1="$RED not in red "

Renk çıkışlarını değişkenlerde saklamak istiyorsanız, değişkene $'...'değişmez bir kaçış karakteri koymak için ANSI-C quoting ( ) kullanabilirsiniz.

Bunu yapmak için, sizin tanımı değiştirebilir GREEN, REDve NONEbunların değeri gerçek çıkış sırası yani.

GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'

Bunu yaparsanız PS1, tek tırnak işareti ile ilk çalışmanız gerekir:

PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '

Ancak, ikinci bir sorununuz olacaktır.

Bunu çalıştırmayı deneyin Up Arrow, ardından Home, tuşuna basın ; imleciniz satırın başına gitmeyecektir.

Bunu düzeltmek için, renk kaçış dizilerini PS1içerecek \[ve \]çevresinde olacak şekilde değiştirin

PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '

get_exit_statusÇıktısı hem yazdırma (çıkış kodu) hem de yazdırma dışı karakterler (renk kodları) içerdiğinden ve istemde doğru olarak işaretlemenin bir yolu olmadığından burada düzgün şekilde kullanamazsınız . Koymak \[...\]onu tam olarak yazdırmamak olarak işaretler, ki bu doğru değildir. İşlevi yalnızca uygun renk kodunu yazdıracak şekilde değiştirmeniz ve ardından \[...\]istemde çevrelemeniz gerekir .


\[olduğu \1ve \[bir \2. Bunlar RL_PROMPT_{START,END}_IGNORE, ekranda bilgi istemi uzunluğunu sayarken baytları göz ardı etmesini isteyen bazı readline öğelerine karşılık gelir . Bkz. Lists.gnu.org/archive/html/bug-bash/2015-08/msg00027.html .
Arthur2e5

Şunu @ Arthur2e5 Do \]olduğunu \2? Ve bu yüzden bunun için gerekli mi demek istiyorsun ${exitStatus}? Benim demek istediğim oldu ${exitStatus}o olmadan istemi hareket kaç karakter bash doğru belirlemek gerekir, böylece olmayan baskı karakterler içermediğinden \[ve \]içinde \[${exitStatus}\].
Mikel

Sorun şu ki bazı renkler içeriyor. (ANSI Escapes)
Arthur2e5

@ Arthur2e5 Ew, bunu tamamen özledim. :) Neden renkleri koydun ... boş ver. :)
Mikel

1
"Bash, PS1'inizde echo-e'yi değil, yankıyı etkin bir şekilde çağırıyor" - bu yanlış ya da sadece noktayı kaçırıyor. Bash ters eğik çizgi-kaçar gibi zaman genişletilebilir \eve \033(ve \[/ \], \uve \histemi itibaren), sadece yapar önce değişkenleri genişleyen. Yani PS1='\e[1;31m red'işe yarıyor, red='\e[1;31m'; PS1='$red red'değil.
ilkkachu

3

Çalıştırdığınızda PS1='${RED}\h $(get_path) ${exitStatus}${NONE} ', PS1değişken ${RED}\h $(get_path) ${exitStatus}${NONE}yalnızca \hbir bilgi istemi kaçış dizisi olarak ayarlanır . Sonra hızlı diziler genişletilir elde edildi ( ${RED}darkstar $(get_path) ${exitStatus}${NONE}), kabuk, örneğin değişken açılımlar gibi bilinen açılımlar gerçekleştirir. Görünen bir bilgi istemi alırsınız \e[1;31mdarkstar PATH 0\e[m. Yol boyunca hiçbir şey \edizileri gerçek kaçış karakterlerine genişletemez .

Çalıştırdığınızda PS1="${RED}\h $(get_path) ${exitStatus}${NONE} ", PS1değişken olarak ayarlanır \e[1;31m\h PATH 0\e[m. Değişkenler RED, exitStatusve NONEgörevlendirme sırasında genişletilir. Daha sonra hızlı üç hızlı çıkış sıralarını içeren ( \e, \hve \etekrar). Bu aşamada genişletilecek kabuk değişkeni yoktur.

Renkleri görmek için, gerçek çıkış karakterlerini içerecek renk değişkenlerine ihtiyacınız vardır. Bunu şu şekilde yapabilirsiniz:

RED=$'\033[1;31m'
NONE=$'\033[m'
PS1='\[${RED}\]\h \w $?\[${NONE}\] '

$'…'eğik çizgi-sekizlik dizileri ve bu gibi bazı eğik çizgi-harf dizileri genişletir \n, ancak bu derece dahil değil \e. İsteminizde üç değişiklik daha yaptım:

  • \[…\]Renk değiştiren komutlar gibi yazdırılmayan dizilerin çevresinde kullanın . Aksi takdirde, ekran istemin genişliğini anlayamadığı için ekranınız bozulacaktır.
  • \w geçerli dizini yazdırmak için yerleşik bir kaçış dizisidir.
  • İlk etapta $?istemiyorsanız, istemde göstermek için karmaşık bir şeye ihtiyacınız yoktur PROMPT_COMMAND.

Bence bu fikir başarıya yeşil, başarısızlığa kırmızı gelmekti.
mattdm

Evet, PS1yanlış, ama kullanmak $'...'için tavsiye REDve GREENdogbane kullanarak çalışması gerekir PS1.
Mikel

1

Deneyin:

PS1='`exitStatus=$?;if [ $exitStatus -eq 0 ];then echo "\['${GREEN}'\]";else echo "\['${RED}'\]";fi;echo "\h $(get_path) ${exitStatus}${NONE}"`'

1
Teşekkürler, bu işe yarıyor, ancak bir if-ifadesini bilgi istemi içine yerleştirmek zorunda kalmadan bunu başarmanın bir yolu var mı?
dogbane

1

İşte yaklaştığım yaklaşım, kullanımından kaçınıyor PROMPT_COMMAND.

# This function is called from a subshell in $PS1,
# to provide a colourised visual indicator of the exit status of the last run command
__COLOURISE_EXIT_STATUS() {
    # uncomment the next line for exit code output after each command, useful for debugging and testing
    #printf -- "\nexit code: $1\n" >&2
    [[ 0 == "$1" || 130 == "$1" ]] && printf -- "$GREEN" || printf -- "$RED"
}

O zaman benim $PS1şöyle:

PS1='# ${debian_chroot:+($debian_chroot)}'"${GREEN}\u${YELLOW}@${DARK_YELLOW}\h${WHITE}:${LIGHT_BLUE}\w${WHITE}\n"'\[$(__COLOURISE_EXIT_STATUS $?)\]# \$'"\[${WHITE}\] "

1
Bu özel durumda önemli olmasa da, tek değerin sahip $?olabileceği bir tamsayı olduğu için printf '%b' "$GREEN"bunun yerine gerçekten kullanmalısınız . Ayrıca, bash-completion tarafından ön ekli __veya ile kullanılan işlev adlarını kullanmaktan kaçının _.
nyuszika7h

1

Buyrun - Bu Ubuntu ve diğer Linux'larda (Linuxen?) Benim İçin Çalışıyor (TM).

Çıkış kodu algılamasını koymanın nedeni $PS1, bir ana bilgisayarın $PROMPT_COMMAND.bashrc okunmadan önce salt okunur olarak ayarlanmış olmasıdır.


0

Çünkü PROMPT_COMMAND, bir işlevi tanımlamak ve bunu kullanmak daha temizdir:

prompt_command() {
    # ...
}
PROMPT_COMMAND=prompt_command
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.