যদি আপনাকে অবশ্যই আউটপুট সংরক্ষণ করতে হয় এবং আপনি কোনও অ্যারে চান তবে mapfileএটি সহজ করে তোলে।
প্রথমে বিবেচনা করুন আপনি যদি আপনার কমান্ডের আউটপুটটি আদৌ সঞ্চয় হবেআপনি যদি না করেন তবে কমান্ডটি চালান।
আপনি যদি সিদ্ধান্ত নেন যে আপনি কোনও কমান্ডের আউটপুটকে লাইনের অ্যারে হিসাবে পড়তে চান তবে এটি সত্য যে এটি করার একটি উপায় হ'ল গ্লোব্বিং নিষ্ক্রিয় করা, IFSলাইনগুলিতে বিভক্ত হওয়া, ( )অ্যারে তৈরির বাক্য গঠনের অভ্যন্তরে কমান্ড প্রতিস্থাপন ব্যবহার করা এবং IFSতারপরে পুনরায় সেট করা, যা মনে হয় তার চেয়ে জটিল । টেরডনের উত্তর সেই পদ্ধতির কিছুটি জুড়ে। তবে আমি আপনাকে পরামর্শ দিচ্ছি যে পরিবর্তে পাঠ্যগুলি লাইনের অ্যারে হিসাবে পড়ার জন্য mapfileবাশ শেলের বিল্ট ইন কমান্ডটি ব্যবহার করুন। এখানে একটি সরল কেস রয়েছে যেখানে আপনি ফাইল থেকে পড়ছেন:
mapfile < filename
এটি লাইনগুলিকে অ্যারেতে পাঠায় MAPFILE। ইনপুট পুনঃনির্দেশ ছাড়াই আপনি শেলটির স্ট্যান্ডার্ড ইনপুট (সাধারণত আপনার টার্মিনাল) দ্বারা নামকৃত ফাইলটির পরিবর্তে পড়বেন । ডিফল্ট ব্যতীত অন্য কোনও অ্যারেতে পড়তে এর নামটি দিন। উদাহরণস্বরূপ, এটি অ্যারেতে পড়ে :< filenamefilenameMAPFILElines
mapfile lines < filename
আপনি যে ডিফল্ট আচরণ পরিবর্তন করতে বেছে নিতে পারেন তা হ'ল লাইনের শেষ প্রান্তে থাকা নিউলাইন অক্ষরগুলি সেখানে রেখে দেওয়া হয়েছে; এগুলি প্রতিটি অ্যারের উপাদানটিতে সর্বশেষ অক্ষর হিসাবে উপস্থিত হয় (যদি না কোনও নিউলাইন অক্ষর ব্যতীত ইনপুটটি শেষ না হয়, যার ক্ষেত্রে শেষ উপাদানটির একটি না থাকে)। এই নিউলাইনগুলি চম্প করতে যাতে তারা অ্যারেটিতে উপস্থিত না হয়, -tবিকল্পটি পাস করুন mapfile। উদাহরণস্বরূপ, এটি অ্যারে পড়ে recordsএবং এর অ্যারে উপাদানগুলিতে নতুন লাইনের অক্ষরগুলি লিখে না:
mapfile -t records < filename
আপনি -tঅ্যারের নামটি না দিয়েও ব্যবহার করতে পারেন ; এটি, এর একটি অন্তর্নিবিষ্ট অ্যারে নামের MAPFILEসাথেও কাজ করে।
mapfileশেল সমর্থন builtin অন্যান্য অপশন, এবং এটি অন্যথায় যেমন প্রার্থনা করা যেতে পারে readarray। বিশদ জন্য চালান help mapfile(এবং help readarray)।
তবে আপনি কোনও ফাইল থেকে পড়তে চান না, আপনি একটি কমান্ডের আউটপুট থেকে পড়তে চান। এটি অর্জন করতে, প্রক্রিয়া বিকল্প ব্যবহার করুন । এই কমান্ডের সার্চ হুকুম থেকে লাইন some-commandদিয়ে arguments...তার কমান্ড লাইন আর্গুমেন্ট এবং তাদের মধ্যে স্থানগুলির mapfileএর ডিফল্ট বিন্যাস MAPFILE, তাদের সসীম সম্পর্কে newline অক্ষর সরানো হয়েছে:
mapfile -t < <(some-command arguments...)
প্রক্রিয়া প্রতিস্থাপনটি একটি আসল ফাইলনামের সাথে প্রতিস্থাপন করে যেখানে থেকে চালনার আউটপুটটি পড়া যায়। ফাইলটি একটি নিয়মিত ফাইলের পরিবর্তে একটি নামযুক্ত পাইপ এবং উবুন্টুতে এটির নাম দেওয়া হবে (কখনও কখনও অন্য কিছু সংখ্যার সাথেও রয়েছে ) তবে আপনাকে বিশদটি নিয়ে নিজেকে উদ্বিগ্ন হওয়ার দরকার নেই, কারণ শেলটি এটির যত্ন নেয় সব পর্দার পিছনে।<(some-command arguments...)some-command arguments.../dev/fd/6363
পরিবর্তে ব্যবহার করে আপনি বিকল্প প্রতিস্থাপনটি ভুলে যেতে পারেন বলে মনে করতে পারেন , তবে এটি কার্যকর হবে না কারণ যখন আপনার একাধিক কমান্ডের পাইপলাইন পৃথক করে আলাদা করা হয় , তখন ব্যাশ সাবশেলের সমস্ত কমান্ড চালায় । এইভাবে এবং উভয়ই তাদের নিজস্ব পরিবেশে চালিত হয় , আপনি যে পাইপলাইনটি চালান সেই শেলের পরিবেশ থেকে শুরু করে তবে পৃথক। সাবচেলে যেখানে সঞ্চালিত হয় সেখানে অ্যারেটি পপুলেশন হয় না , তবে কমান্ড শেষ হয়ে গেলে অ্যারেটি ফেলে দেওয়া হয়। কলারের জন্য কখনও তৈরি বা পরিবর্তিত হয় না।some-command arguments... | mapfile -t|some-command arguments...mapfile -tmapfile -tMAPFILEMAPFILE
এখানে কি উদাহরণ মধ্যে terdon এর উত্তর দেখে মনে হচ্ছে, সম্পূর্ণতা, যদি আপনি ব্যবহার mapfile:
mapfile -t dirs < <(find . -type d)
for d in "${dirs[@]}"; do
echo "DIR: $d"
done
এটাই. আপনি প্রয়োজন হবে না যদি পরীক্ষা IFSহয় না তা হয় ট্র্যাক এবং কি মান রাখতে একটি newline এটি সেট, তারপর রিসেট করতে অথবা পুনরায় সেট না এটা পরে। আপনি নিষ্ক্রিয় করতে না globbing (উদাহরণস্বরূপ, সঙ্গে set -f) - যা সত্যিই প্রয়োজন হয়, আপনি গম্ভীরভাবে যে পদ্ধতি ব্যবহার যেহেতু ফাইলের নামের থাকতে পারে যদি *, ?এবং [এটা --then পুনরায়-সক্ষম (set +f ) পরে।
আপনি সেই নির্দিষ্ট লুপটিকে পুরোপুরি একটি একক printfকমান্ডের সাথেও প্রতিস্থাপন করতে পারেন - যদিও এটি আসলে কোনও উপকার নয় mapfile, আপনি mapfileঅ্যারেটি তৈরি করতে অন্য কোনও পদ্ধতি ব্যবহার করেন কিনা তা করতে পারেন । এখানে একটি সংক্ষিপ্ত সংস্করণ:
mapfile -t < <(find . -type d)
printf 'DIR: %s\n' "${MAPFILE[@]}"
এটি মনে রাখা জরুরী যে, টেরডন যেমন উল্লেখ করেছেন , লাইন বাই লাইন অপারেটিং সর্বদা যথাযথ নয় এবং নতুন লাইনে থাকা ফাইল নামগুলির সাথে সঠিকভাবে কাজ করবে না। আমি সেইভাবে ফাইলগুলির নামকরণের বিরুদ্ধে প্রস্তাব দিই, তবে তা পারে দৃর্ঘটনায় সহ ঘটে।
আসলেই এক-আকারের-ফিট-সব সমাধান নেই।
আপনি "সমস্ত পরিস্থিতিতে একটি জেনেরিক কমান্ড" এবং ব্যবহারের পদ্ধতির জন্য জিজ্ঞাসা করেছিলেন mapfile লক্ষ্যে কিছুটা পদ্ধতির পদ্ধতির জন্য বলেছেন, তবে আমি আপনাকে অনুরোধ করছি আপনার প্রয়োজনীয়তাগুলি নিয়ে পুনর্বিবেচনা করার জন্য।
উপরে প্রদর্শিত টাস্কটি কেবলমাত্র একটি একক findকমান্ড দিয়ে আরও ভালভাবে অর্জন করা যেতে পারে :
find . -type d -printf 'DIR: %p\n'
আপনি প্রতিটি লাইনের শুরুতে sedযুক্ত DIR: করতে একটি বাহ্যিক কমান্ডও ব্যবহার করতে পারেন । এটি তর্কসাপেক্ষভাবে কিছুটা কুৎসিত এবং এটির আদেশের বিপরীতে এটি ফাইললাইমগুলিতে নতুন লাইন যুক্ত অতিরিক্ত "উপসর্গ" যুক্ত করবে, তবে এটির ইনপুট নির্বিশেষে এটি কাজ করে যাতে এটি আপনার প্রয়োজন অনুসারে বাছাই করে এবং এটি আউটপুটটি আউটপুট পড়ার পক্ষে আরও ভাল is পরিবর্তনশীল বা অ্যারে :
find . -type d | sed 's/^/DIR: /'
যদি আপনাকে প্রতিটি ডিরেক্টরিতে তালিকা তৈরি করতে এবং পাওয়া যায় যেমন some-commandযেমন একটি আর্গুমেন্ট হিসাবে ডিরেক্টরিটির পথ চালানো এবং পাস করা, তবে findআপনাকে এটি করতে দেয়:
find . -type d -print -exec some-command {} \;
অন্য উদাহরণ হিসাবে, আসুন প্রতিটি লাইনে একটি উপসর্গ যোগ করার সাধারণ কার্যে ফিরে আসি। ধরুন আমি আউটপুট দেখতে চাই help mapfileতবে লাইনগুলিকে সংখ্যায়িত করব। আমি আসলে mapfileএটির জন্য ব্যবহার করব না বা অন্য কোনও পদ্ধতি যা এটিকে শেল ভেরিয়েবল বা শেল অ্যারে পড়বে। ধরুন help mapfile | cat -nআমি যে ফর্ম্যাট করতে চাই তা দেয় না, আমি এটি ব্যবহার করতে পারি awk:
help mapfile | awk '{ printf "%3d: %s\n", NR, $0 }'
একক ভেরিয়েবল বা অ্যারেতে কমান্ডের সমস্ত আউটপুট পড়া কখনও কখনও দরকারী এবং উপযুক্ত, তবে এর বড় অসুবিধা রয়েছে।আপনার শেলটি ব্যবহারের অতিরিক্ত জটিলতা কেবলমাত্র যখনই উপস্থিত থাকে না যখন বিদ্যমান কমান্ড বা বিদ্যমান কমান্ডগুলির সংমিশ্রণটি আপনার প্রয়োজনীয় বা আরও ভাল প্রয়োজন হতে পারে তবে কমান্ডের পুরো আউটপুট মেমরির মধ্যে সংরক্ষণ করতে হবে। কখনও কখনও আপনি বুঝতে পারেন যে এটি কোনও সমস্যা নয় তবে কখনও কখনও আপনি কোনও বড় ফাইলটি প্রক্রিয়াজাত করতে পারেন।
একটি বিকল্প যা সাধারণত চেষ্টা করা হয় - এবং কখনও কখনও ঠিক করা হয় - read -rলুপের সাহায্যে ইনপুট লাইন বাই লাইনে পড়া । পরবর্তী লাইনে অপারেটিং করার সময় যদি আপনার পূর্ববর্তী লাইনগুলি সংরক্ষণ করার প্রয়োজন না হয় এবং আপনাকে দীর্ঘ ইনপুট ব্যবহার করতে হয়, তবে এটি এর চেয়ে ভাল হতে পারে mapfile। তবে এটির ক্ষেত্রেও এড়ানো উচিত যখন আপনি কেবল এটি কোনও কাজটি করতে পারে এমন কোনও আদেশের সাথে পাইপ করতে পারেন, যা বেশিরভাগ ক্ষেত্রে ।