बैश: शीघ्र में बाहर निकलने की स्थिति प्रदर्शित करें:


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)'

निम्नलिखित मुझे सही एग्जिटस्टैटस देता है लेकिन रंग चर का विस्तार नहीं किया जाता है:

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

हालाँकि, नीचे वाला मुझे रंग देता है लेकिन बाहर निकलने की स्थिति अपडेट नहीं होती है:

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

ऐसा करने का सही तरीका क्या है? मैं इसे कैसे ठीक कर सकता हूं ताकि एक्ज़िटस्टैटस और रंग दोनों काम करें?

जवाबों:


8

गिल्स ने आपकी मुख्य समस्या की पहचान की, लेकिन मैं इसे अलग तरीके से समझाने की कोशिश करना चाहता था।

बैश प्रॉम्प्ट में किसी भी चर का विस्तार करने से पहले केवल विशेष प्रॉम्प्ट से बच जाता है । इसका मतलब यह है कि \eप्रॉम्प्ट से विस्तारित एक चर का उपयोग करना काम नहीं करता है, भले ही यह सीधे काम करता है PS1

उदाहरण के लिए, यह उम्मीद के अनुसार काम करता है, और लाल पाठ देता है:

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

लेकिन यह नहीं है, यह सिर्फ शीघ्र में एक शाब्दिक डालता है \e:

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

यदि आप चर में रंग से $'...'बचना चाहते हैं, तो आप एएनएसआई-सी का उपयोग कर सकते हैं ( ) को चर में एक शाब्दिक बच चरित्र डाल सकते हैं।

ऐसा करने के लिए, आप की अपनी परिभाषा को बदल सकते हैं GREEN, REDऔर NONE, इसलिए उनके मूल्य वास्तविक भागने अनुक्रम है।

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

यदि आप ऐसा करते हैं, PS1तो एकल उद्धरण के साथ आपका पहला काम होना चाहिए:

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

हालाँकि, तब आपको दूसरी समस्या होगी।

उसे चलाने का प्रयास करें, फिर दबाएं Up Arrow, फिर Home, और आपका कर्सर लाइन की शुरुआत में वापस नहीं जाएगा।

इसे ठीक करने के लिए, रंग से बचने के दृश्यों PS1को शामिल करने \[और \]उसके आसपास बदलने के लिए , जैसे

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

आप get_exit_statusयहां ठीक से उपयोग नहीं कर सकते , क्योंकि इसके आउटपुट में प्रिंटिंग (एग्जिट कोड) और नॉन-प्रिंटिंग कैरेक्टर (कलर कोड) दोनों शामिल हैं, और प्रॉम्प्ट में इसे सही तरीके से चिह्नित करने का कोई तरीका नहीं है। पुटिंग \[...\]इसे पूर्ण रूप से गैर-मुद्रण के रूप में चिह्नित करेगी, जो सही नहीं है। आपको फ़ंक्शन बदलना होगा ताकि यह केवल उचित रंग-कोड को प्रिंट करे, और फिर इसे \[...\]प्रॉम्प्ट से घेर ले ।


\[है \1, और \[है \2। वे कुछ रीडलाइन की RL_PROMPT_{START,END}_IGNOREचीज़ से मेल खाते हैं जो स्क्रीन पर शीघ्र लंबाई की गिनती करते समय बाइट्स को अनदेखा करने के लिए कहता है। Lists.gnu.org/archive/html/bug-bash/2015-08/msg00027.html देखें ।
आर्थर 2 ई 5

@ Arthur2e5 क्या आपका मतलब \]है \2? और क्या आपका मतलब है कि इसकी आवश्यकता क्यों है ${exitStatus}? मेरा कहना था कि ${exitStatus}गैर-मुद्रण वर्ण नहीं हैं, इसलिए बैश को सही ढंग से यह निर्धारित करने में सक्षम होना चाहिए कि यह कितने वर्णों को बिना \[और उसके भीतर संकेत के ले जाता \]है \[${exitStatus}\]
मिकेल

समस्या यह है कि इसमें कुछ - रंग शामिल हैं। (एएनएसआई एस्केप)
आर्थर २ ई ५

@ Arthur2e5 ईव, मैं पूरी तरह से याद किया। :) तुम रंग क्यों डालोगे ... कोई बात नहीं। :)
मिकेल

1
"बैश प्रभावी रूप से आपके PS1 पर इको कॉल कर रहा है, इको-ईई नहीं" - अच्छी तरह से यह गलत है या बस बिंदु याद आ रहा है। बैश का विस्तार करता है बैकस्लैश-पलायन की तरह \eऔर \033(और \[/ \], \uऔर \hशीघ्र से), यह सिर्फ ऐसा नहीं करता है से पहले चर का विस्तार। तो PS1='\e[1;31m red'काम करता है, red='\e[1;31m'; PS1='$red red'नहीं।
ilkkachu

3

जब आप चलते हैं PS1='${RED}\h $(get_path) ${exitStatus}${NONE} ', तो PS1चर को सेट किया जाता है ${RED}\h $(get_path) ${exitStatus}${NONE}, जहां केवल \hएक त्वरित भागने का क्रम होता है। प्रॉम्प्ट सीक्वेंस का विस्तार (पैदावार ) होने के बाद${RED}darkstar $(get_path) ${exitStatus}${NONE} , शेल सामान्य विस्तार जैसे कि चर विस्तार करता है। आपको एक प्रदर्शित संकेत मिलता है जो दिखता है \e[1;31mdarkstar PATH 0\e[m। जिस तरह से कुछ भी नहीं \eवास्तविक दृश्यों पात्रों के लिए दृश्यों का विस्तार करता है ।

जब आप चलते हैं PS1="${RED}\h $(get_path) ${exitStatus}${NONE} ", तो PS1चर सेट हो जाता है \e[1;31m\h PATH 0\e[m। चर RED, exitStatusऔर NONEअसाइनमेंट के समय विस्तारित होते हैं। तो फिर शीघ्र तीन शीघ्र भागने दृश्यों में शामिल है ( \e, \h, और \eफिर से)। इस स्तर पर विस्तार करने के लिए कोई शेल चर नहीं हैं।

रंगों को देखने के लिए, आपको वास्तविक भागने वर्णों के लिए रंग चर की आवश्यकता होती है। आप इसे इस तरह से कर सकते हैं:

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

$'…'बैकस्लैश-ऑक्टल सीक्वेंस और कुछ बैकस्लैश-लेटर सीक्वेंस जैसे \n, लेकिन शामिल नहीं है \e। मैंने आपके संकेत पर तीन अन्य परिवर्तन किए हैं:

  • का प्रयोग करें \[…\]इस तरह के रंग बदलने आदेशों के रूप में गैर मुद्रण दृश्यों के आसपास। अन्यथा आपका प्रदर्शन समाप्त हो जाएगा क्योंकि बैश प्रॉम्प्ट की चौड़ाई का पता नहीं लगा सकता है।
  • \w वर्तमान निर्देशिका मुद्रित करने के लिए एक अंतर्निहित एस्केप अनुक्रम है।
  • $?यदि आपको PROMPT_COMMANDपहले स्थान पर नहीं है, तो आपको संकेत में जटिल कुछ भी दिखाने की आवश्यकता नहीं है ।

मुझे लगता है कि यह विचार सफलता के लिए संकेत को हरा और विफलता पर लाल होना था।
mattdm

हाँ, PS1गलत है, लेकिन उपयोग करने के लिए सलाह $'...'के लिए REDऔर GREENयह dogbane का उपयोग काम करना चाहिए PS1
मिकेल

1

प्रयत्न:

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

1
धन्यवाद, यह काम करता है, लेकिन क्या शीघ्रता के भीतर एक if-statement को एम्बेड किए बिना इसे पूरा करने का कोई तरीका है?
dogbane

1

यहां मैं जिस दृष्टिकोण के साथ गया हूं, वह इसके उपयोग से बचा जाता है 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"
}

तब मेरा $PS1इस प्रकार है:

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

1
हालांकि यह इस विशेष मामले में कोई फर्क नहीं पड़ता, क्योंकि एकमात्र मान $?एक पूर्णांक हो सकता है, आपको वास्तव में printf '%b' "$GREEN"इसके बजाय उपयोग करना चाहिए । इसके अलावा, फ़ंक्शन नामों के उपयोग से बचें जिनके साथ __या _जैसा कि वे बैश-पूर्णता द्वारा उपयोग किया जाता है।
nyuszika7h

1

यहां आप जाते हैं - यह वर्क्स फॉर मी (टीएम) उबंटू और अन्य लिनक्स (लिनक्सन?) में काम करता है।

एग्जिट कोड का पता लगाने का $PS1कारण यह है कि एक होस्ट के पास $PROMPT_COMMAND.bashrc पढ़ने से पहले केवल पढ़ने के लिए सेट होता है।


0

इसके लिए PROMPT_COMMAND, किसी फ़ंक्शन को परिभाषित करना और उसका उपयोग करना क्लीनर है:

prompt_command() {
    # ...
}
PROMPT_COMMAND=prompt_command
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.