PS1 और PROMPT_COMMAND में क्या अंतर है


108

इस भयानक धागे पर एक नज़र डालते हुए मैंने देखा कि कुछ उदाहरण उपयोग करते हैं

PS1="Blah Blah Blah"

और कुछ उपयोग

PROMPT_COMMAND="Blah Blah Blah"

(और कुछ दोनों का उपयोग करें) जब बैश शेल में प्रॉम्प्ट सेट करें। दोनों के बीच क्या अंतर है? एक SO खोज और यहां तक ​​कि थोड़ी सी व्यापक Google खोज से मुझे परिणाम नहीं मिल रहे हैं, इसलिए उत्तर की तलाश करने के लिए सही जगह की लिंक की भी सराहना की जाएगी।

जवाबों:


59

GNU बैश डॉक्टर पृष्ठ से: http://www.gnu.org/software/bash/manual/bashref.html

PROMPT_COMMAND
    If set, the value is interpreted as a command to execute before
    the printing of each primary prompt ($PS1).

मैंने इसका इस्तेमाल कभी नहीं किया, लेकिन मैं इसे वापस इस्तेमाल कर सकता था जब मेरे पास केवल श था।


67

PROMPT_COMMAND में साधारण बैश स्टेटमेंट हो सकते हैं जबकि PS1 वैरिएबल में वैरिएम के लिए 'वर्ण' जैसे विशेष वर्ण भी हो सकते हैं।

उदाहरण के लिए यहाँ मेरा bash प्रॉम्प्ट है जो PROMPT_COMMAND और PS1 दोनों का उपयोग करता है। PROMPT_COMMAND में बैश कोड यह बताता है कि आप किस git ब्रांच में हो सकते हैं और यह दिखाते हैं कि प्रॉम्प्ट पर, अंतिम रन प्रक्रिया की बाहर निकलने की स्थिति, होस्टनाम और pwd के बेसनेम। चर आरईटी अंतिम निष्पादित कार्यक्रम के रिटर्न मूल्य को संग्रहीत करता है। यह देखने के लिए सुविधाजनक है कि क्या टर्मिनल में मेरे द्वारा चलाए गए अंतिम प्रोग्राम की त्रुटि और त्रुटि कोड था। संपूर्ण PROMPT_COMMAND अभिव्यक्ति के आसपास के बाहरी भाग पर ध्यान दें। इसमें PS1 शामिल है ताकि PROMPT_COMMAND चर का मूल्यांकन होने पर हर बार इस चर का पुनर्मूल्यांकन किया जाए।

PROMPT_COMMAND='RET=$?;\
  BRANCH="";\
  ERRMSG="";\
  if [[ $RET != 0 ]]; then\
    ERRMSG=" $RET";\
  fi;\
  if git branch &>/dev/null; then\
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2);\
  fi;
PS1="$GREEN\u@\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";'

उदाहरण आउटपुट गैर-गिट निर्देशिका में इस तरह दिखता है:

sashan@dhcp-au-122 Documents  $ false
sashan@dhcp-au-122 Documents  1 $ 

और एक गिट निर्देशिका में आप शाखा का नाम देखते हैं:

sashan@dhcp-au-122 rework mybranch $ 

अपडेट करें

टिप्पणियों और बॉब के उत्तर को पढ़ने के बाद मुझे लगता है कि इसे लिखना, जैसा कि वह बताता है कि बेहतर है। यह जितना मैंने मूल रूप से ऊपर लिखा था, उससे कहीं अधिक कायम रखने योग्य है, जहां PS1 चर PROMPT_COMMAND के अंदर सेट किया गया है, जो कि खुद एक सुपर कॉम्प्लेक्स स्ट्रिंग है जिसका मूल्यांकन बैश द्वारा रनटाइम पर किया जाता है। यह काम करता है, लेकिन यह होने की तुलना में अधिक जटिल है। निष्पक्ष होने के लिए मैंने लिखा कि PROMPT_COMMAND ने लगभग 10 साल पहले अपने लिए काम किया था और इसने काम नहीं किया और इसके बारे में बहुत ज्यादा नहीं सोचा।

उन लोगों के लिए जो मेरी बातों में संशोधन कर चुके हैं, मैंने मूल रूप से PROMPT_COMMAND के लिए कोड अलग फाइल में डाल दिया है (जैसा बॉब ने वर्णित किया है) और फिर उस स्ट्रिंग को प्रतिध्वनित करें जिसे मैं PS1 करने का इरादा रखता हूं:

GREEN="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour

if [ -z $SCHROOT_CHROOT_NAME ]; then
    SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
if [[ $RET != 0 ]]; then
    ERRMSG=" $RET"
fi
if which git &>/dev/null; then
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2)
else
    BRANCH="(git not installed)"
fi
echo "${GREEN}\u@\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} \$ $RESTORE"

और मेरे .bashrc में

function prompt_command {
    RET=$?
    export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command

1
आप अपनी एक पंक्ति को छोटा कर सकते हैं if git branch &>/dev/null ; then\ :। यह stdout और stderr दोनों को / dev / null में रीडायरेक्ट करता है। tldp.org/LDP/abs/html/io-redirection.html

3
निर्यात करने की कोई आवश्यकता नहीं है PROMPT_COMMAND
dolmen

2
मुझे लगता है कि सीलिंग की टिप्पणी इस उत्तर के लिए भी बहुत सही है:Don't set PS1 in PROMPT_COMMAND! Set variables in PROMPT_COMMAND and use them in PS1
phil294

2
मुझे कोई कारण नहीं दिखता है, PS1ऑनलाइन बदलाव करना क्यों PROMPT_COMMANDनुकसानदेह है। यह सही उपयोगी कोड है। बॉब के उत्तर के विपरीत, PS1चर का सही ढंग से निर्माण किया गया था। यह आपकी वास्तविक स्थिति के आधार पर बहुत अधिक परिष्कृत बैश संकेत देता है।
क्रिश्चियन वुल्फ

2
@ChristianWolf PS1अंदर का निर्माण PROMPT_COMMANDकोई उद्देश्य नहीं है। यह एक उदाहरण है कि यह कैसे नहीं करना है। PS1एक बार निर्माण करें .bash_profile, बस दोहरे उद्धरण चिह्नों के बजाय एकल उद्धरणों का उपयोग करें, ताकि प्रत्येक त्वरित के दौरान चर प्रतिस्थापन का मूल्यांकन किया जा सके।
पाल

46

अंतर यह है कि PS1 वास्तविक प्रांप्ट स्ट्रिंग है, और PROMPT_COMMAND एक कमांड है, जिसे प्रॉम्प्ट से ठीक पहले निष्पादित किया जाता है। यदि आप प्रॉम्प्ट बनाने का सबसे सरल, सबसे लचीला तरीका चाहते हैं, तो यह कोशिश करें:

इसे अपने .bashrc में रखें:

function prompt_command {
  export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command

फिर एक स्क्रिप्ट लिखें (बैश, पर्ल, रूबी: अपनी पसंद), और इसे ~ / bin / bash_prompt में रखें।

स्क्रिप्ट किसी भी जानकारी का उपयोग कर सकती है जिसे वह शीघ्र निर्माण करना पसंद करता है। यह बहुत सरल IMO है क्योंकि आपको कुछ बारोक प्रतिस्थापन भाषा सीखने की ज़रूरत नहीं है जो केवल PS1 चर के लिए विकसित की गई थी।

आप सोच सकते हैं कि आप ऐसा केवल PROMPT_COMMAND को सीधे ~ / bin / bash_prompt पर सेट करके और PS1 को खाली स्ट्रिंग पर सेट करके ही कर सकते हैं। यह पहली बार काम करने के लिए प्रकट होता है, लेकिन आपको जल्द ही पता चलता है कि रीडलाइन कोड PS1 को वास्तविक प्रॉम्प्ट पर सेट होने की उम्मीद करता है, और जब आप इतिहास में बैकवर्ड स्क्रॉल करते हैं, तो परिणामस्वरूप चीजें गड़बड़ हो जाती हैं। इस समाधान के कारण PS1 हमेशा नवीनतम प्रॉम्प्ट को प्रतिबिंबित करता है (क्योंकि फ़ंक्शन वास्तविक PS1 को शेल के इनवॉइस इंस्टेंस द्वारा उपयोग किया जाता है), और इससे रीडलाइन और कमांड इतिहास ठीक काम करता है।


17
PS1में सेट नहीं है PROMPT_COMMAND! में चर सेट करें PROMPT_COMMANDऔर उनका उपयोग करें PS1। अन्यथा आप PS1भागने के क्रम का उपयोग करने की क्षमता को ढीला कर देंगे जैसे \uया \h। आपको उन्हें पुनः स्थापित करना होगा PROMPT_COMMAND। यह संभव हो सकता है लेकिन यह संभव नहीं है कि खोने के आसपास काम करें \[और \]जो गैर मुद्रण योग्य पात्रों की शुरुआत और अंत को चिह्नित करें। इसका मतलब है कि आप प्रांप्ट की लंबाई के बारे में टर्मिनल को भ्रमित किए बिना रंगों का उपयोग नहीं कर सकते। और यह readlineदो पंक्तियों के बीच कमांड को संपादित करते समय भ्रमित करता है । अंत में आप स्क्रीन पर एक बड़ी गड़बड़ है।
छत

1
@ सच सच! आपके PS1 के प्रारूप को बदलने और दोनों दुनिया का सर्वश्रेष्ठ पाने के लिए PROMPT_COMMAND का उपयोग कर सकते हैं
2grit

3
PROMPT_COMMANDमुद्रण से पहले निष्पादित किया जाता है PS1। मुझे PS1अंदर से सेटिंग करने में कोई समस्या नहीं दिख रही है PROMPT_COMMAND, क्योंकि PROMPT_COMMANDसमाप्त होने के बाद , शेल प्रिंट होगा PS1, जिसे PROMPT_COMMAND(या इस मामले में, अंदर prompt_command) से संशोधित किया गया था ?
फेलिप अल्वारेज

3
चेतावनी: PROMPT_COMMAND का उपयोग आम तौर पर वर्णों को तुरंत प्रिंट करने के लिए नहीं किया जाना चाहिए। PS1 के बाहर मुद्रित वर्णों को बैश द्वारा नहीं गिना जाता है, जिसके कारण यह कर्सर और स्पष्ट वर्णों को गलत तरीके से रखेगा। PS1 को सेट करने के लिए PROMPT_COMMAND का उपयोग करें या एम्बेडिंग आदेशों को देखें। ( आर्क विकी स्रोत )
meffect

3
मुझे यह नहीं मिलता कि क्यों हर कोई PS1 में कमांड प्रतिस्थापन का उपयोग करने के बजाय PROMPT_COMMAND में कुछ चालें करने की कोशिश export PS1='$(~/bin/bash_prompt)'करता है, वही काम बग- सा दिखता है
pal

10

से man bash:

PROMPT_COMMAND

यदि सेट किया जाता है, तो मूल्य को प्रत्येक प्राथमिक संकेत जारी करने से पहले एक कमांड के रूप में निष्पादित किया जाता है।

PS1

इस पैरामीटर का मान विस्तारित है (नीचे PROMPTING देखें) और प्राथमिक संकेत स्ट्रिंग के रूप में उपयोग किया जाता है। डिफ़ॉल्ट मान '' \ s- \ v \ $ '' है।

यदि आप केवल शीघ्र स्ट्रिंग सेट करना चाहते हैं, तो PS1अकेले उपयोग करना पर्याप्त है:

PS1='user \u on host \h$ '

यदि आप शीघ्र छापने से पहले कुछ और करना चाहते हैं, तो उपयोग करें PROMPT_COMMAND। उदाहरण के लिए, यदि आप कैश्ड राइट टू डिस्क को सिंक करना चाहते हैं, तो आप लिख सकते हैं:

PROMPT_COMMAND='sync'

1
आप PS1बिना आवश्यकता के टर्मिनल का शीर्षक भी निर्धारित कर सकते हैं PROMPT_COMMAND, क्योंकि शीर्षक सेट करने वाले अनुक्रम को PS1लिपटे हुए \[और के साथ शामिल किया जा सकता है \]
dolmen

1
@ डोलमेन ऑल राइट। तो फिर कुछ और करते हैं, जैसे कि गतिशील रूप से एक पर्यावरण चर सेट करना।
साइपर 29'16

@ यदि आप गतिशील रूप से पर्यावरण चर सेट कर सकते हैं PS1, तो यह केवल उप- समुच्चय में सेट किया जाएगा, इसलिए आपको इसका मान वापस नहीं मिल सकता है। लेकिन आपका उदाहरण तुच्छ हैPS1='$(sync)user \u on host \h$ '
पाल

1

अंतर यह है कि

  • यदि आप से अधूरी लाइन आउटपुट करते हैं PROMPT_COMMAND, तो यह आपके बैश प्रॉम्प्ट को खराब कर देगा
  • PS1विकल्प \Hऔर दोस्त
  • PROMPT_COMMANDअपनी सामग्री चलाता है, अपनी सामग्री PS1का उपयोग शीघ्रता से करता है।

PS1प्रत्येक प्रांप्ट पर परिवर्तनीय विस्तार और कमांड प्रतिस्थापन, मनमाना कोड चलाने के PROMPT_COMMANDलिए PS1या मान असाइन करने के लिए उपयोग करने की आवश्यकता नहीं है । आप आसानी से export PS1='$(uuidgen) $RANDOM'एक बार में कर सकते हैं .bash_profile, बस एकल उद्धरण का उपयोग करें


0

हाँ, तो वास्तव में इसे नीचे कील करने की कोशिश करने के लिए:

  • PROMPT_COMMANDएक आसान बैश सुविधा चर / फ़ंक्शन है, लेकिन कड़ाई से बोलना, कुछ भी नहीं है जो PS1अकेले, सही का उपयोग करके नहीं किया जा सकता है ?

मेरा मतलब है, अगर कोई प्रॉम्प्ट के साथ एक और चर को प्रॉम्प्ट के बाहर सेट करना चाहता है : शेल के आधार पर, उस वेरिएबल को संभवतः पहले या बाहर (सबसे खराब स्थिति) घोषित करने की आवश्यकता होगी, किसी को इससे पहले FIFO पर प्रतीक्षा कर रहे कुछ के साथ फैंसी प्राप्त करना पड़ सकता है कॉलिंग (और फिर से सशस्त्र ); , कुछ परेशानी का कारण आप कुछ फैंसी regex का उपयोग कर रहे विशेष रूप से अगर हो सकता है; लेकिन अन्यथा: एक आदेश प्रतिस्थापन के भीतर (और, कोने के मामलों में, स्पष्ट उपधाराओं का उपयोग करके) कुछ भी पूरा कर सकता है ?$PS1$PS1$PS1\u \hPROMPT_COMMAND$PS1

सही?

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