वही आउटपुट प्राप्त करने के लिए जिसे आप अपने प्रश्न में नोट करते हैं, इसकी आवश्यकता है:
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 \b
ackspaces का एक समूह बनाना शुरू नहीं करना चाहते हैं तब तक इसके लिए थोड़ा अधिक है और फिर उनके वर्ण गणना को संतुलित करने की कोशिश कर रहे हैं ... 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
।