
वही आउटपुट प्राप्त करने के लिए जिसे आप अपने प्रश्न में नोट करते हैं, इसकी आवश्यकता है:
PS1='${PS2c##*[$((PS2c=0))-9]}- > '
PS2='$((PS2c=PS2c+1)) > '
आपको कॉन्ट्रास्ट की जरूरत नहीं है। उन दो पंक्तियों में यह सब किसी भी शेल में किया जाएगा जो POSIX संगतता के करीब कुछ भी दिखाएगा।
- > cat <<HD
1 > line 1
2 > line $((PS2c-1))
3 > HD
line 1
line 2
- > echo $PS2c
0
लेकिन मुझे यह पसंद आया। और मैं इस काम के मूल सिद्धांतों को प्रदर्शित करना चाहता था जो इस काम को थोड़ा बेहतर बनाता है। इसलिए मैंने इसे थोड़ा संपादित किया। मैंने इसे /tmpअभी के लिए रोक दिया है लेकिन मुझे लगता है कि मैं इसे अपने लिए भी रखने जा रहा हूं। यह यहाँ है:
cat /tmp/prompt
PROMPT SCRIPT:
ps1() { IFS=/
set -- ${PWD%"${last=${PWD##/*/}}"}
printf "${1+%c/}" "$@"
printf "$last > "
}
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
PS2='$((PS2c=PS2c+1)) > '
नोट: हाल ही में सीखा यश के , मैंने इसे कल बनाया था। जो भी कारण के लिए यह %cस्ट्रिंग के साथ हर तर्क के पहले बाइट को प्रिंट नहीं करता है - हालांकि डॉक्स उस प्रारूप के लिए विस्तृत-चार एक्सटेंशन के बारे में विशिष्ट थे और इसलिए यह संबंधित हो सकता है - लेकिन यह सिर्फ ठीक करता है%.1s
यह पूरी बात है। वहाँ दो मुख्य बातें चल रही हैं। और ऐसा ही दिखता है:
/u/s/m/man3 > cat <<HERE
1 > line 1
2 > line 2
3 > line $((PS2c-1))
4 > HERE
line 1
line 2
line 3
/u/s/m/man3 >
पदच्छेद $PWD
हर बार $PS1इसका मूल्यांकन किया जाता है और इसे $PWDशीघ्र जोड़ने के लिए प्रिंट करता है । लेकिन मुझे $PWDअपनी स्क्रीन पर पूरी भीड़ पसंद नहीं है , इसलिए मैं मौजूदा निर्देशिका में नीचे दिए गए वर्तमान पथ में हर ब्रेडक्रंब का पहला अक्षर चाहता हूं, जिसे मैं पूरी तरह से देखना चाहता हूं। ऐशे ही:
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cd /
/ > cd ~
/h/mikeserv >
यहाँ कुछ चरण हैं:
IFS=/
हम वर्तमान $PWDऔर सबसे विश्वसनीय तरीका है कि $IFSविभाजन पर है के साथ विभाजित करने के लिए जा रहे हैं /। बाद में इसके साथ परेशान करने की कोई आवश्यकता नहीं है - बाहर से यहाँ पर सभी विभाजन $@को अगले कमांड में शेल के स्थितीय पैरामीटर सरणी द्वारा परिभाषित किया जाएगा :
set -- ${PWD%"${last=${PWD##/*/}}"}
तो यह थोड़ा मुश्किल है, लेकिन मुख्य बात यह है कि हम प्रतीकों $PWDपर विभाजन कर रहे हैं /। मैं $lastबाईं और सबसे दाईं ओर सबसे अधिक /स्लैश के बीच होने वाले किसी भी मूल्य के बाद हर चीज को असाइन करने के लिए पैरामीटर विस्तार का उपयोग करता हूं । इस तरह से मुझे पता है कि अगर मैं अभी हूँ /और केवल एक ही हूँ /तो $lastअभी भी पूरा बराबर होगा $PWDऔर $1खाली हो जाएगा। यह मायने रखता है। मैं भी इसे देने $lastसे $PWDपहले पूंछ के अंत से पट्टी $@।
printf "${1+%c/}" "$@"
तो यहाँ - जब तक ${1+is set}हम अपने प्रत्येक शेल के तर्कों printfके पहले %cहाॅटर हैं - जिसे हमने अभी-अभी अपनी वर्तमान में प्रत्येक निर्देशिका में सेट किया है $PWD- शीर्ष निर्देशिका को कम - विभाजित करते हैं /। इसलिए हम अनिवार्य रूप से हर निर्देशिका के पहले चरित्र को ही प्रिंट कर रहे हैं, $PWDलेकिन शीर्ष पर। यह महत्वपूर्ण है, हालांकि साकार करने के लिए यह केवल होता है अगर है $1सब पर सेट हो जाता है, जो जड़ में नहीं होगा /या एक पर से हटा /में के रूप में ऐसी /etc।
printf "$last > "
$lastवह चर है जिसे मैंने अभी हमारी शीर्ष निर्देशिका को सौंपा है। तो अब यह हमारी शीर्ष निर्देशिका है। यह बताता है कि अंतिम वक्तव्य में क्या है या नहीं। और यह >अच्छे उपाय के लिए साफ सुथरा होता है ।
लेकिन इस बारे में क्या होगा?
और फिर $PS2सशर्त की बात है । मैंने पहले दिखाया था कि यह कैसे किया जा सकता है जिसे आप अभी भी नीचे पा सकते हैं - यह मूल रूप से गुंजाइश का एक मुद्दा है। लेकिन जब तक आप printf \backspaces का एक समूह बनाना शुरू नहीं करना चाहते हैं तब तक इसके लिए थोड़ा अधिक है और फिर उनके वर्ण गणना को संतुलित करने की कोशिश कर रहे हैं ... ugh। इसलिए मैं यह करता हूं:
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
फिर, ${parameter##expansion}दिन बचाता है। हालांकि यह थोड़ा अजीब है - हम वास्तव में चर सेट करते हैं, जबकि हम इसे खुद से पट्टी करते हैं। हम इसके नए मूल्य का उपयोग करते हैं - मध्य-पट्टी सेट करते हैं - जिस गोला से हम पट्टी करते हैं। आप समझ सकते हैं? हम ##*अपने वेतन वृद्धि के सिर से अंतिम चरित्र तक सभी को पट्टी करते हैं जो कुछ भी हो सकता है [$((PS2c=0))-9]। हम इस तरह से मूल्य का उत्पादन नहीं करने की गारंटी देते हैं, और फिर भी हम इसे असाइन करते हैं। यह बहुत अच्छा है - मैंने पहले कभी ऐसा नहीं किया है। लेकिन POSIX भी हमें गारंटी देता है कि यह सबसे पोर्टेबल तरीका है जो यह किया जा सकता है।
और यह पोसिक्स-निर्दिष्ट के लिए धन्यवाद है ${parameter} $((expansion))जो इन परिभाषाओं को वर्तमान शेल में रखता है बिना आवश्यकता के कि हम उन्हें अलग-अलग उपधारा में सेट करें, भले ही हम उनका मूल्यांकन करें। और यही कारण है कि यह काम करता है dashऔर shसाथ ही साथ यह अंदर bashऔर भीतर भी करता है zsh। हम शेल / टर्मिनल आश्रित बच का उपयोग करते हैं और हम चर का परीक्षण स्वयं करते हैं। यही पोर्टेबल कोड को त्वरित बनाता है ।
बाकी काफी सरल है - बस हर बार हमारे काउंटर $PS2का मूल्यांकन किया जाता है जब तक कि $PS1एक बार फिर से रीसेट नहीं हो जाता। ऐशे ही:
PS2='$((PS2c=PS2c+1)) > '
तो अब मैं कर सकता हूँ:
DEM DEMO
ENV=/tmp/prompt dash -i
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cat <<HERE
1 > line 1
2 > line 2
3 > line $((PS2c-1))
4 > HERE
line 1
line 2
line 3
/u/s/m/man3 > printf '\t%s\n' "$PS1" "$PS2" "$PS2c"
$(ps1)${PS2c##*[$((PS2c=0))-9]}
$((PS2c=PS2c+1)) >
0
/u/s/m/man3 > cd ~
/h/mikeserv >
SH DEMO
यह वही में काम करता है bashया sh:
ENV=/tmp/prompt sh -i
/h/mikeserv > cat <<HEREDOC
1 > $( echo $PS2c )
2 > $( echo $PS1 )
3 > $( echo $PS2 )
4 > HEREDOC
4
$(ps1)${PS2c##*[$((PS2c=0))-9]}
$((PS2c=PS2c+1)) >
/h/mikeserv > echo $PS2c ; cd /
0
/ > cd /usr/share
/u/share > cd ~
/h/mikeserv > exit
जैसा कि मैंने ऊपर कहा, प्राथमिक समस्या यह है कि आपको यह विचार करने की आवश्यकता है कि आप अपनी गणना कहाँ करते हैं। आपको मूल शेल में राज्य नहीं मिलता है - इसलिए आप वहां गणना नहीं करते हैं। आपको उप-स्थिति में राज्य मिलता है - इसलिए कि आप कहां गणना करते हैं। लेकिन आप मूल शेल में परिभाषा करते हैं।
ENV=/dev/fd/3 sh -i 3<<\PROMPT
ps1() { printf '$((PS2c=0)) > ' ; }
ps2() { printf '$((PS2c=PS2c+1)) > ' ; }
PS1=$(ps1)
PS2=$(ps2)
PROMPT
0 > cat <<MULTI_LINE
1 > $(echo this will be line 1)
2 > $(echo and this line 2)
3 > $(echo here is line 3)
4 > MULTI_LINE
this will be line 1
and this line 2
here is line 3
0 >
man 1 mktemp।