प्रिंटफ अपेक्षा से अधिक तर्क क्यों छापता है?


9

यह शेल स्क्रिप्ट प्रिंटिंग इनपुट दो बार क्यों है?

मुझे उम्मीद थी कि स्क्रिप्ट 5 के बाद इनपुट्स को नजरअंदाज करेगी।

स्क्रिप्ट:

#! /bin/bash
echo "Enter 5 words : "
read  a b c d e 
printf "> %s %s %s %s %s <" $a $b $c $d $e

आउटपुट:

user@linux:~$ pico ifs2.sh
user@linux:~$ ./ifs2.sh
Enter 5 words : 
1 2 3 4 5 
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
Enter 5 words : 
1 2 3 4 5 6
> 1 2 3 4 5 <> 6     <user@linux:~$ ./ifs2.sh
Enter 5 words : 
1 2 3 4 5 6 7 8 9 0
> 1 2 3 4 5 <> 6 7 8 9 0 <user@linux:~$ 

और, निम्न स्क्रिप्ट काम नहीं करती है जो $ IFS के लिए सेट है। क्यों?

#! /bin/bash    
old="$IFS"
IFS=":"
echo "IFS = $IFS"
echo "Enter 5 words : "
read  a b c d e 
printf "> %s %s %s %s %s <" $a $b $c $d $e    
IFS="$old"

आउटपुट:

user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words : 
1 2 3 4 5  
> 1 2 3 4 5      <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words : 
1 2 3 4 5
> 1 2 3 4 5     <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words : 
1:2:3:4:5
> 1 2 3 4 5 <user@linux:~$ 

एक प्रारूप विनिर्देशक के साथ जुड़े भागने के साथ printfकिसी भी समय बंद करो । जैसे:\c%bprintf %s%\ d%b thing 3 "${var+\cquit printing if set}\nelse do a newline" and 0 keep\ going.
mikeserv

जवाबों:


18

आपको तीन समस्याएं हैं:

  1. साथ readहै, अगर वहाँ इनपुट में क्षेत्रों की तुलना में कम चर नाम कर रहे हैं, पिछले वर सीमांकक के साथ लाइन पर सभी शेष क्षेत्रों, करने के लिए बाध्य कर दिया जाएगा। इसका मतलब है कि $eहो जाता है 5 6अपनी पहली अप्रत्याशित उदाहरण में।
  2. क्योंकि सभी $a.. $eअयोग्य हैं, उनके मूल्यों को क्षेत्र विभाजन से गुजरना पड़ता है । यदि $eपकड़ " 5 6" है तो यह कमांड में दो तर्कों में विस्तार करता है।
  3. printfएक बार %प्रतिस्थापन, बार- बार कई तर्कों का उपयोग करते हुए, अपने सभी तर्कों का उपभोग करता है । इस दस्तावेज में दफन किया गया है :

    formatसंकार्य तर्क ऑपरेंड को पूरा करने के रूप में अक्सर आवश्यक के रूप में पुन: उपयोग किया किया जाएगा। किसी भी अतिरिक्त cया sरूपांतरण विनिर्देशक का मूल्यांकन किया जाएगा जैसे कि एक नल स्ट्रिंग तर्क की आपूर्ति की गई थी; अन्य अतिरिक्त रूपांतरण विनिर्देशों का मूल्यांकन किया जाएगा जैसे कि एक शून्य तर्क की आपूर्ति की गई थी।

    दूसरे शब्दों में, यदि अप्रयुक्त तर्क हैं तो यह फिर से शुरू होता है और उन्हें शुरुआत से ही संसाधित करता है, जिसमें पूरे प्रारूप स्ट्रिंग भी शामिल है। यह उपयोगी है जब आप संपूर्ण सरणी को प्रारूपित करना चाहते हैं, कहते हैं:

    printf '%b ' "${array[@]}"

    आपके printfआदेश में से प्रत्येक से एक तर्क मिलता है $a.. $dऔर फिर बहुत से बाकी हैं $e। जब $e" 5 6" होता है, तो printfदो घूम जाते हैं, दूसरा सिर्फ प्रारूपण के 6लिए होता है। जब यह 5 6 7 8 9 10दूसरा मुद्रण के लिए प्रतिस्थापन की पूरी श्रृंखला है।


आप एक अतिरिक्त डमी फ़ील्ड को जोड़कर readऔर अपने पैरामीटर प्रतिस्थापन को उद्धृत करके इन सभी से बच सकते हैं (जो हमेशा एक अच्छा विचार है):

read  a b c d e dummy
printf "> %s %s %s %s %s <" "$a" "$b" "$c" "$d" "$e"

यह देगा:

Enter 5 words : 
1 2 3 4 5 6 7 8 9 10
> 1 2 3 4 5 <

dummyसभी अतिरिक्त फ़ील्ड्स प्राप्त करता है, और printfकेवल उन पाँच तर्कों को प्राप्त करता है जिनकी आपको अपेक्षा थी।


आपके दूसरे संपादित किए गए प्रश्न का एक समान उत्तर है: केवल aएक मूल्य प्राप्त होता IFSहै जब कोई स्थान नहीं होता है। इसका मतलब है $b.. $eविस्तार कुछ भी नहीं है, इसलिए printfकेवल एक ही तर्क मिलता है। प्रारूप स्ट्रिंग से आपके स्थान मुद्रित किए जाते हैं, उनके बीच में प्रतिस्थापित कुछ भी नहीं ("के रूप में अगर एक नल स्ट्रिंग तर्क की आपूर्ति की गई थी")।


मैंने फिर से "$ a" ..... "$ e" का उपयोग करके 2 स्क्रिप्ट का परीक्षण किया। दूसरी स्क्रिप्ट फिर से वही समस्या दे रही है।

3
क्वोटिंग से दूसरी स्क्रिप्ट पर कोई फर्क नहीं पड़ने वाला है। एक ही तार के रूप aमें मूल्य है 1 2 3 4 5और यह एक ही बार में प्रतिस्थापित हो जाता है।
माइकल होमर

6
 printf "> %s < " 1 2 3

छप जाएगा

 > 1 <> 2 <> 3 <

  printf "> %s %s <" 1 2 3

प्रिंट

 > 1 2 <> 3  <

printf अपने प्रारूप स्ट्रिंग को संतुष्ट करने के लिए सभी तर्कों को खाता है और तब तक दोहराता है जब तक कि सभी तर्क संसाधित नहीं हो जाते।

दूसरी स्क्रिप्ट इसलिए काम करती है क्योंकि केवल $aउसे ही सौंपा गया है और इसलिए कमांड अतिरिक्त पुनरावृत्तियों में नहीं बहता है (केवल एक पुनरावृति है)।


यह व्यवहार प्रदान किए गए पाठ में प्रलेखित है help printf:

... सभी तर्कों का उपभोग करने के लिए प्रारूप का पुनः उपयोग आवश्यक है। यदि प्रारूप की आवश्यकता से कम तर्क हैं, तो अतिरिक्त प्रारूप विनिर्देशन ऐसा व्यवहार करता है जैसे कि एक शून्य मान या अशक्त स्ट्रिंग, जैसा कि उपयुक्त था, आपूर्ति की गई थी। ...

और http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html द्वारा अनिवार्य है


यह व्यवहार क्यों है? क्या यह प्रलेखित है?
शिप्लू मोकादिम

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