কিছু লোকের এমন ভুল ধারণা রয়েছে যা readএকটি লাইন পড়ার আদেশ command এটা না।
readএকটি (সম্ভবত ব্যাকস্ল্যাশ-অবিরত) লাইন থেকে শব্দগুলি পড়ে , যেখানে শব্দগুলি $IFSসীমানাযুক্ত হয় এবং সীমানা ছাড়ানো (বা অবিরত রেখাগুলি) থেকে বাঁচতে ব্যাকস্ল্যাশ ব্যবহার করা যেতে পারে।
জেনেরিক সিনট্যাক্সটি হ'ল:
read word1 word2... remaining_words
readএকটি সময়ে stdin এক বাইট লেখা পর্যন্ত এটি খুঁজে বের করে একটি unescaped newline অক্ষর (অথবা শেষ অফ ইনপুট), splits যে বিভাজন ফল মধ্যে জটিল নিয়ম এবং দোকান অনুযায়ী $word1, $word2... $remaining_words।
উদাহরণস্বরূপ একটি ইনপুট যেমন:
<tab> foo bar\ baz bl\ah blah\
whatever whatever
এবং এর ডিফল্ট মান সহ $IFS, read a b cবরাদ্দ করা হবে:
$a ⇐ foo
$b ⇐ bar baz
$c ⇐ blah blahwhatever whatever
এখন যদি কেবল একটি যুক্তি পাস হয় তবে তা হয়ে যায় না read line। এখনও আছে read remaining_words। ব্যাকস্ল্যাশ প্রসেসিং এখনও সম্পন্ন হয়েছে, আইএফএস শ্বেতস্পেস অক্ষরগুলি এখনও শুরু এবং শেষ থেকে সরানো হয়েছে।
-rবিকল্প ব্যাকস্ল্যাশ প্রক্রিয়াকরণ সরিয়ে ফেলা হয়। সুতরাং উপরে একই কমান্ড -rপরিবর্তে বরাদ্দ করা হবে
$a ⇐ foo
$b ⇐ bar\
$c ⇐ baz bl\ah blah\
এখন বিভাজনের অংশের জন্য এটি উপলব্ধি করা গুরুত্বপূর্ণ যে এর জন্য দুটি শ্রেণীর অক্ষর রয়েছে $IFS: আইএফএস শ্বেতস্পেস অক্ষর (যেমন স্থান এবং ট্যাব (এবং নিউলাইন, যদিও এখানে আপনি -d ব্যবহার না করেই কিছু আসে যায় না), যা ঘটেছিল এর ডিফল্ট মান হতে হবে $IFS) এবং অন্যান্য। এই দুই শ্রেণীর চরিত্রের চিকিত্সা আলাদা।
সঙ্গে IFS=:( :না একটি IFS হোয়াইটস্পেস অক্ষর হচ্ছে), মত একটি ইনপুট :foo::bar::বিভক্ত করা হবে "", "foo", "", barএবং ""(এবং একটি অতিরিক্ত ""কিছু বাস্তবায়নের সঙ্গে যে যদিও ছাড়া কোন ব্যাপার না read -a)। আমরা যদি :স্থানটির সাথে এটি প্রতিস্থাপন করি তবে বিভাজনটি কেবল fooএবং এর মধ্যেই করা হয় bar। এটি শীর্ষস্থানীয় এবং পিছনের দিকগুলি অগ্রাহ্য করা হয় এবং সেগুলির ক্রমগুলি একের মতো বিবেচিত হয়। হোয়াইটস্পেস এবং অ-শ্বেতস্পেস অক্ষরগুলিকে একত্রিত করার সময় অতিরিক্ত নিয়ম রয়েছে $IFS। কিছু বাস্তবায়ন আইএফএস ( IFS=::বা IFS=' ') এর অক্ষরগুলিকে দ্বিগুণ করে বিশেষ চিকিত্সা যুক্ত / সরাতে পারে ।
সুতরাং এখানে, আমরা যদি না চান যে শীর্ষস্থানীয় এবং অনুসরণযোগ্য অবিরত শ্বেতস্পেস অক্ষরগুলি ছাঁটাতে হবে, আমাদের আইএফএস থেকে সেই আইএফএস সাদা স্থান অক্ষরগুলি সরিয়ে ফেলতে হবে।
এমনকি আইএফএস-নন-হোয়াইটস্পেস অক্ষরগুলি সহ, যদি ইনপুট লাইনে সেই অক্ষরগুলির মধ্যে একটি (এবং কেবলমাত্র একটি) থাকে এবং এটি পসিক্স শেলগুলির ( IFS=: read -r wordযেমন কোনও সংস্করণ foo:নয়) লাইনটির শেষ অক্ষর (যেমন কোনও ইনপুটে পছন্দ করে ) থাকে তবে সেই ইনপুট একটি শব্দ হিসাবে বিবেচনা করা হয় কারণ এই শেলগুলিতে, অক্ষরগুলি টার্মিনেটর হিসাবে বিবেচিত হয় , সুতরাং এটি থাকবে , না ।zshpdkshfoo$IFSwordfoofoo:
সুতরাং, readবিল্টিনের সাথে ইনপুটগুলির একটি লাইন পড়ার আধ্যাত্মিক উপায় হ'ল:
IFS= read -r line
(নোট করুন যে বেশিরভাগ readবাস্তবায়নের জন্য, এটি কেবল পাঠ্য লাইনের জন্য কাজ করে কারণ NUL অক্ষরটি ব্যতীত সমর্থনযোগ্য নয় zsh)।
var=value cmdসিনট্যাক্স ব্যবহার নিশ্চিত IFSকরে যে এই cmdআদেশের সময়কালের জন্য আলাদাভাবে সেট করা আছে ।
ইতিহাস নোট
readBuiltin বোর্ন শেল চালু এবং পড়তে ইতিমধ্যে ছিল শব্দ , না লাইন। আধুনিক পসিক্স শেলগুলির সাথে কয়েকটি গুরুত্বপূর্ণ পার্থক্য রয়েছে।
বোর্ন শেল readএকটি -rবিকল্প (যা কর্ন শেল দ্বারা প্রবর্তিত হয়েছিল) সমর্থন করে না , সুতরাং সেখানে কিছু sed 's/\\/&&/g'আছে এমন ইনপুট প্রাক প্রসেসিং ছাড়া ব্যাকস্ল্যাশ প্রক্রিয়াকরণ অক্ষম করার কোন উপায় নেই।
বোর্ন শেলটিতে দুটি শ্রেণির অক্ষরের ধারণা নেই (যা আবার কেএসএস দ্বারা প্রবর্তিত হয়েছিল)। বোর্ন শেল সমস্ত অক্ষর একই চিকিত্সা ভুগা যেমন IFS হোয়াইটস্পেস অক্ষর ksh না, যে IFS=: read a b cমত একটি ইনপুট উপর foo::barদায়িত্ব অর্পণ করবে barকরার $b, না খালি স্ট্রিং।
বোর্ন শেল এ, সাথে:
var=value cmd
যদি cmdকোনও অন্তর্নির্মিত (যেমন readহয়) varথাকে তবে শেষ হয়ে যাওয়ার valueপরে সেট থাকে cmd। এটি বিশেষত সমালোচিত $IFSকারণ বোর্ন শেলের মধ্যে, $IFSসমস্ত বিস্তৃত করতে ব্যবহৃত হয়, কেবল বিস্তৃতি নয়। এছাড়াও, আপনি যদি $IFSবোর্ন শেল থেকে স্থানের অক্ষরটি সরিয়ে ফেলেন তবে "$@"আর কাজ করবে না।
বোর্ন শেল-এ, একটি যৌগিক কমান্ড পুনর্নির্দেশের ফলে এটি একটি সাব-শেলের মধ্যে চালিত হয় (প্রথম দিকের সংস্করণগুলিতে, এমনকি পছন্দ মতো read var < fileবা exec 3< file; read var <&3কাজ করে না), সুতরাং readটার্মিনালের ব্যবহারকারীর ইনপুট ব্যতীত বোর্ন শেল ব্যবহার করা বিরল was (যেখানে সেই লাইন ধারাবাহিকতা পরিচালনা করে তোলে)
কিছু ইউনিসে (এইচপি / ইউএক্সের মতো, এর মধ্যে একটিও রয়েছে util-linux) এখনও একটি lineইনপুট পড়ার জন্য কমান্ড রয়েছে ( এটি সিঙ্গেল ইউনিক্স স্পেসিফিকেশন সংস্করণ 2 অবধি স্ট্যান্ডার্ড ইউনিক্স কমান্ড আপ হিসাবে ব্যবহৃত হত )।
এটি মূলত একইরকম head -n 1যে এটি একবারে এক বাইট পড়ে তা নিশ্চিত করার জন্য এটি এক লাইনের বেশি পড়বে না। এই সিস্টেমগুলিতে, আপনি এটি করতে পারেন:
line=`line`
অবশ্যই, এর অর্থ একটি নতুন প্রক্রিয়া তৈরি করা, একটি কমান্ড চালানো এবং পাইপের মাধ্যমে তার আউটপুটটি পড়ুন, সুতরাং ksh এর চেয়ে অনেক কম দক্ষ IFS= read -r line, তবে এখনও অনেক বেশি স্বজ্ঞাত।