এটি শুধু প্রতি বনাম প্রিন্টফ নয়
প্রথমে, read a b cঅংশটি দিয়ে কী ঘটে তা বুঝতে দিন । ভেরিয়েবলের readডিফল্ট মানের উপর ভিত্তি করে শব্দ বিভাজন সম্পাদন করবে IFSযা স্পেস-ট্যাব-নতুনলাইন, এবং এর ভিত্তিতে সমস্ত কিছু ফিট করবে। ভেরিয়েবলগুলি ধরে রাখার জন্য যদি আরও ইনপুট থাকে তবে এটি বিভক্ত অংশগুলিকে প্রথম ভেরিয়েবলের সাথে ফিট করবে এবং যা ফিট করা যায় না - তা শেষের দিকে চলে যাবে। আমি যা বলতে চাইছি তা এখানে:
bash-4.3$ read a b c <<< "one two three four"
bash-4.3$ echo $a
one
bash-4.3$ echo $b
two
bash-4.3$ echo $c
three four
এটি ঠিক এভাবেই bashএর ম্যানুয়ালটিতে বর্ণিত হয়েছে (উত্তরের উদ্ধৃতিটি দেখুন)।
আপনার ক্ষেত্রে যা ঘটে তা হ'ল, 1 এবং 2 a এবং b ভেরিয়েবলের সাথে খাপ খায় এবং সি সমস্ত কিছু গ্রহণ করে যা হয় 3 4 5 6।
আপনি যা অনেক সময় দেখতে পাবেন তা হ'ল লোকেরা while IFS= read -r line; do ... ; done < input.txtলাইন দিয়ে টেক্সট ফাইলগুলি পড়তে ব্যবহার করে। আবার IFS=শব্দ বিভাজন নিয়ন্ত্রণ করার কারণেই এখানে রয়েছে বা আরও সুনির্দিষ্টভাবে - এটি অক্ষম করুন এবং পাঠ্যটির একটি একক লাইন ভেরিয়েবলে পড়ুন। এটি যদি না থাকে readতবে প্রতিটি পৃথক শব্দকে lineভেরিয়েবলের সাথে ফিট করার চেষ্টা করা হবে । তবে এটি আরেকটি গল্প, যা আমি আপনাকে পরে পড়াশোনা করতে উত্সাহিত করি, যেহেতু while IFS= read -r variableখুব ঘন ঘন ব্যবহৃত কাঠামো।
প্রতিধ্বনি বনাম প্রিন্টফ আচরণ
echoআপনি এখানে কি আশা করতে চান। এটি আপনার ভেরিয়েবলগুলি ঠিক যেমন readসাজিয়েছে তে প্রদর্শিত করে। এটি পূর্বের আলোচনায় ইতিমধ্যে প্রদর্শিত হয়েছে।
printfএটি অত্যন্ত বিশেষ, কারণ এটিগুলির সমস্ত ক্লান্ত না হওয়া অবধি ফরম্যাট স্ট্রিংয়ে ফিটিং ভেরিয়েবলগুলি রাখা থাকবে। সুতরাং আপনি যখন printf "%d, %d, %d \n" $a $b $cপ্রিন্টফ করেন তখন 3 দশমিকের সাথে ফর্ম্যাট স্ট্রিং দেখতে পান তবে 3 টির চেয়ে বেশি যুক্তি রয়েছে (কারণ আপনার ভেরিয়েবলগুলি প্রকৃতপক্ষে পৃথক 1,2,3,4,5,6 তে প্রসারিত হয়)। এটি বিভ্রান্তিকর লাগতে পারে তবে সি ভাষায় আসল printf() ফাংশনটি কী করে তা থেকে উন্নত আচরণ হিসাবে এটি একটি কারণে উপস্থিত রয়েছে ।
আপনি এখানে যা আউটপুটকে প্রভাবিত করেন তা হ'ল আপনার ভেরিয়েবলগুলি উদ্ধৃত হয় না, যা শেলটি (না printf) ভেরিয়েবলগুলি 6 টি পৃথক আইটেমে বিভক্ত করতে দেয় allows উদ্ধৃতি দিয়ে এটি তুলনা করুন:
bash-4.3$ read a b c <<< "1 2 3 4"
bash-4.3$ printf "%d %d %d\n" "$a" "$b" "$c"
bash: printf: 3 4: invalid number
1 2 3
$cভেরিয়েবলটি উদ্ধৃত হবার কারণে , এটি এখন একটি সম্পূর্ণ স্ট্রিং হিসাবে স্বীকৃত 3 4, এবং এটি %dবিন্যাসে ফিট করে না , যা কেবল একটি একক পূর্ণসংখ্যা
এখন উদ্ধৃতি না দিয়ে একই করুন:
bash-4.3$ printf "%d %d %d\n" $a $b $c
1 2 3
4 0 0
printf আবার বলেছেন: "ঠিক আছে, আপনার কাছে 6 টি আইটেম রয়েছে তবে ফর্ম্যাটটি কেবল 3 টি দেখায়, তাই আমি ফিটিং স্টাফ রাখি এবং ব্যবহারকারীর আসল ইনপুটটির সাথে আমার যা মেলে না পারে তা ফাঁকা রেখে দেব"।
এবং এই সমস্ত ক্ষেত্রে আপনাকে এর জন্য আমার কথাটি নিতে হবে না। strace -e trace=execveকমান্ডটি আসলে "দেখুন" কী করে তা কেবল নিজের জন্য চালান এবং দেখুন:
bash-4.3$ strace -e trace=execve printf "%d %d %d\n" $a $b $c
execve("/usr/bin/printf", ["printf", "%d %d %d\\n", "1", "2", "3", "4"], [/* 80 vars */]) = 0
1 2 3
4 0 0
+++ exited with 0 +++
bash-4.3$ strace -e trace=execve printf "%d %d %d\n" "$a" "$b" "$c"
execve("/usr/bin/printf", ["printf", "%d %d %d\\n", "1", "2", "3 4"], [/* 80 vars */]) = 0
1 2 printf: ‘3 4’: value not completely converted
3
+++ exited with 1 +++
অতিরিক্ত নোট
চার্লস ডাফি মন্তব্যে যথাযথভাবে নির্দেশিত হওয়ার সাথে bashসাথে তার নিজস্ব বিল্ট-ইন রয়েছে printfযা আপনি আপনার কমান্ডটিতে ব্যবহার করছেন, straceআসলে /usr/bin/printfশেলটির সংস্করণ নয়, সংস্করণ কল করবে । ছোটখাটো পার্থক্য বাদ দিয়ে, এই বিশেষ প্রশ্নের প্রতি আমাদের আগ্রহের জন্য স্ট্যান্ডার্ড ফর্ম্যাট স্পেসিফায়ার একই এবং আচরণ একই।
যে বিষয়টি মনে রাখা উচিত তা হল printfসিনট্যাক্সটি echoসি বা অন্য কোনও সি-এর মতো ভাষার সাথে পরিচিত যা printf()এটিতে কাজ করে তার চেয়ে অনেক বেশি বহনযোগ্য (এবং তাই পছন্দসই) than বনাম বিষয়ে টেরডনের দ্বারা এই দুর্দান্ত উত্তরটি দেখুন । আপনি যদি উবুন্টুর নির্দিষ্ট সংস্করণে আপনার নির্দিষ্ট শেলের সাথে আউটপুট তৈরি করতে পারেন তবে আপনি যদি বিভিন্ন সিস্টেমে স্ক্রিপ্টগুলি পোর্ট করতে চলেছেন তবে আপনার সম্ভবত প্রতিধ্বনির চেয়ে পছন্দ করা উচিত । সম্ভবত আপনি উবুন্টু এবং সেন্টোস মেশিনের সাথে কাজ করা একটি শিক্ষানবিস সিস্টেম অ্যাডমিনিস্ট্রেটর, বা এমনকি ফ্রিবিএসডি - কে জানেন - তাই এই ক্ষেত্রে আপনাকে পছন্দ করতে হবে।printfechoprintf
বাশ ম্যানুয়াল থেকে উদ্ধৃতি, বিল্টিন কম্যান্ডস বিভাগে বিক্রয় করুন
[-ers] [-a aname] [-d ডেলিম] [-i পাঠ্য] [-n nchars] [-N nchars] [-p প্রম্পট] [-t টাইমআউট] [-উ fd] [নাম ... ]
একটি লাইন স্ট্যান্ডার্ড ইনপুট থেকে, বা ফাইল বর্ণনাকারী fd থেকে -u বিকল্পের আর্গুমেন্ট হিসাবে সরবরাহ করা হয়, এবং প্রথম শব্দটি প্রথম নামের সাথে, দ্বিতীয় শব্দটির দ্বিতীয় নামতে নির্ধারিত হয়, এবং এভাবেই বাকী থাকে শব্দ এবং তাদের হস্তক্ষেপকারী পৃথক টোড়্স শেষ নাম হিসাবে নির্ধারিত। যদি নামের চেয়ে ইনপুট স্ট্রিম থেকে কম শব্দ পড়ে থাকে তবে অবশিষ্ট নামগুলি খালি মান নির্ধারিত হয়। আইএফএস-এর অক্ষরগুলি শেল সম্প্রসারণের জন্য একই নিয়মগুলি (ওয়ার্ড স্প্লিটিংয়ের নীচে বর্ণিত) ব্যবহার করে একই লাইনগুলিকে শব্দগুলিতে বিভক্ত করতে ব্যবহৃত হয়।
straceকেস এবং অন্যটির মধ্যে একটি উল্লেখযোগ্য পার্থক্য -strace printfব্যবহার করছে/usr/bin/printf, যেখানেprintfসরাসরি ব্যাশে একই নামে শেল বিল্টিন ব্যবহার করা হচ্ছে। এগুলি সর্বদা অভিন্ন হবে না - উদাহরণস্বরূপ, ব্যাশের উদাহরণটির ফর্ম্যাট স্পেসিফায়ার%qএবং নতুন সংস্করণে$()Tসময় বিন্যাসের জন্য রয়েছে।