2011-11-10 9 views
18

यह मेरी बैश स्क्रिप्ट है - मैं बस शून्य के साथ संख्याओं का एक सेट बाएं-पैड करना चाहता हूं :बैश स्क्रिप्ट में printf के साथ विचित्र समस्या: "09" और "08" अमान्य संख्याएं हैं, "07" और "06" ठीक हैं

printf "%04d" "09" 
printf "%04d" "08" 
printf "%04d" "07" 
printf "%04d" "06" 

आउटपुट:

./rename.sh: line 3: printf: 09: invalid number 
0000 
./rename.sh: line 4: printf: 08: invalid number 
0000 
0007 
0006 

क्या ...?

केवल 09 और 08 समस्या पैदा कर रहे हैं: मेरे अनुक्रम में हर दूसरे नंबर ठीक लगता है।

उत्तर

20

यदि आप अपने "09" एक चर में है, तो आप क्या कर सकते हैं

a="09" 
echo "$a" 
echo "${a#0}" 
printf "%04d" "${a#0}" 

यह मदद क्यों करता है? खैर, 0 के साथ एक संख्यात्मक प्रारंभिक शुरुआत है लेकिन दूसरी जगह पर x नहीं है जिसे ऑक्टल मान के रूप में व्याख्या किया जाता है।

ऑक्टल मान में केवल 0 अंक हैं 7, 8 और 9 अज्ञात हैं।

"${a#0}" एक अग्रणी 0 स्ट्रिप्स करता है। परिणामस्वरूप मूल्य को printf पर खिलाया जा सकता है, जो इसे 0 prefixed के साथ, 4 अंकों में उचित रूप से प्रिंट करता है।

आपको लगता है कि आप इस तरह के "009" के रूप में मान मिलता है, चीजों को और अधिक जटिल के रूप में आप के रूप में टिप्पणी में उल्लेख किया है एक पाश जो शुरू में सभी अतिरिक्त 0 रों समाप्त, या एक extglob अभिव्यक्ति का उपयोग करना होगा पाने की उम्मीद है।

+0

क्यों पृथ्वी पर "-1" बिना किसी और सूचना के गलत क्या था ?! – glglgl

+0

आप 'चाहते $ {एक ## 0}' स्थिति में आप निम्न "009" –

+0

कुछ है कि सब पर मदद नहीं करता है - 'एक =" 009 "; echo $ {a ## 0} 'उपज 09. मुझे यहां एक लूप का उपयोग करना होगा - लेकिन ओपी केवल '08',' 09' और '008',' 00 9' के बारे में wroute। हां, यह '#'/'##' सामान regexes के साथ काम नहीं करता है - regex में, कोई 's/^ 0 * // g' लिख सकता है। – glglgl

17

"0" से शुरू होने वाली संख्याओं को ऑक्टल (यानी बेस -8) के रूप में माना जाता है। इसलिए, "8" और "9" वैध अंक नहीं हैं।

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic देखें।

यह व्यवहार सी

जैसी भाषाओं से विरासत में मिली है
+0

धन्यवाद। कोई विचार है कि मैं इन संख्याओं को शून्य के साथ कैसे छोड़ सकता हूं? क्या मुझे पहले अग्रणी शून्य को पट्टी करने की ज़रूरत है, फिर बाएं-पैड - यदि हां, तो कैसे? – Richard

+0

बस तर्क से "0" एस को हटा दें। printf उस प्रारूप स्ट्रिंग के आधार पर आपके लिए बाएं-पैडिंग करेगा। –

+1

धन्यवाद, लेकिन मैं अग्रणी शून्य को कैसे हटा सकता हूं? मैं उसी कारण से 'printf"% d "" 08 "' का उपयोग नहीं कर सकता! (उपर्युक्त उदाहरण मुझे जो करना है, उसका एक बड़ा सरलीकरण है - वास्तव में तर्क एक पैरामीटर है, इसलिए मैं इसे हर बार हाथ से संपादित नहीं कर सकता, मुझे उन्हें जोड़ने से पहले प्रमुख शून्यों को पट्टी करने के लिए एक प्रोग्रामेटिक तरीका चाहिए ...) – Richard

3

बस पैड को Oli's answer में जोड़ने के लिए, क्रम में शून्य के साथ एक नंबर यह पर्याप्त है % के बाद एक 0 डाल करने के लिए, जैसा कि आप ने क्या किया:

printf "%04d" "9"

15

बैश के न्यूमेरिक अंकगणितीय मूल्यांकन वाक्यविन्यास ((...)) निम्नलिखित वाक्यविन्यास के साथ आधार 10 (सही व्याख्या सुनिश्चित करने के लिए) में परिवर्तित कर सकते हैं: ((10#$var))। या, कच्चे नंबर के मामले में: ((10#08))। बहुत आसान & साफ और कहीं भी इस्तेमाल किया जा सकता है, आपको यकीन है कि आधार 10 होना चाहिए, लेकिन एक प्रमुख शून्य की गारंटी नहीं दी जा सकती है।

printf "%04d\n" $((10#09)) 
printf "%04d\n" $((10#08)) 
printf "%04d\n" $((10#07)) 
printf "%04d\n" $((10#06)) 

उत्पादन निम्नलिखित उत्पादन:

तो, अपने उदाहरण में यह इस प्रकार होगा

0009 
0008 
0007 
0006 

इस वाक्य रचना के साथ, जब से तुम तो चर के मूल्य के साथ काम कर रहे हैं बजाय चर के ही, incrementors ((var++)) & decrementors ((var--)) काम नहीं करेगा, लेकिन अभी भी अपेक्षाकृत सफाई से var=$((10#var + 1)) और var=$((10#var - 1)) क्रमश: के रूप में लागू किया जा सकता है।

मैं पहली बार इस समाधान here का सामना करना पड़ा है, लेकिन this answer to a similar Stack Overflow question भी यह दर्शाता है।

+0

ध्यान दें कि यह बैश में काम करता है लेकिन डैश में नहीं (डिफ़ॉल्ट उबंटू खोल)। डैश में, निम्न त्रुटि प्रकट होती है: "अंकगणितीय अभिव्यक्ति: ईओएफ की अपेक्षा" –

3

चल बिन्दु अलग ढंग से नियंत्रित किया जाता है:

printf "%04.f" "009" 

यह सही उत्पादन देता है, (@Oli चार्ल्सवर्थ के प्रति जवाब किसी भी फैंसी bashisms के साथ काम कर के बिना, 0 *** अष्टाधारी के रूप में व्यवहार किया जाता है, लेकिन मुझे लगता है कि विश्वास करते हैं बैश फ्लोटिंग-पॉइंट नंबरों के लिए ऑक्टल/हेक्स पहचानकर्ताओं को अनदेखा करता है)

2

* जोड़ना खोल पैरामीटर विस्तार लालची मिलान (उदाहरण के लिए, Shell Tipps: use internal string handling) बनाता है!

# strip leading 0s 
- a="009"; echo ${a##0} 
+ a="009"; echo ${a##*0} 
+0

यह सही ढंग से काम नहीं करता है। आज़माएं: 'ए =" 00000092323005 "; echo $ {a ## * 0} '। – sorontar

संबंधित मुद्दे