যদি আপনাকে অবশ্যই আউটপুট সংরক্ষণ করতে হয় এবং আপনি কোনও অ্যারে চান তবে mapfile
এটি সহজ করে তোলে।
প্রথমে বিবেচনা করুন আপনি যদি আপনার কমান্ডের আউটপুটটি আদৌ সঞ্চয় হবেআপনি যদি না করেন তবে কমান্ডটি চালান।
আপনি যদি সিদ্ধান্ত নেন যে আপনি কোনও কমান্ডের আউটপুটকে লাইনের অ্যারে হিসাবে পড়তে চান তবে এটি সত্য যে এটি করার একটি উপায় হ'ল গ্লোব্বিং নিষ্ক্রিয় করা, IFS
লাইনগুলিতে বিভক্ত হওয়া, (
)
অ্যারে তৈরির বাক্য গঠনের অভ্যন্তরে কমান্ড প্রতিস্থাপন ব্যবহার করা এবং IFS
তারপরে পুনরায় সেট করা, যা মনে হয় তার চেয়ে জটিল । টেরডনের উত্তর সেই পদ্ধতির কিছুটি জুড়ে। তবে আমি আপনাকে পরামর্শ দিচ্ছি যে পরিবর্তে পাঠ্যগুলি লাইনের অ্যারে হিসাবে পড়ার জন্য mapfile
বাশ শেলের বিল্ট ইন কমান্ডটি ব্যবহার করুন। এখানে একটি সরল কেস রয়েছে যেখানে আপনি ফাইল থেকে পড়ছেন:
mapfile < filename
এটি লাইনগুলিকে অ্যারেতে পাঠায় MAPFILE
। ইনপুট পুনঃনির্দেশ ছাড়াই আপনি শেলটির স্ট্যান্ডার্ড ইনপুট (সাধারণত আপনার টার্মিনাল) দ্বারা নামকৃত ফাইলটির পরিবর্তে পড়বেন । ডিফল্ট ব্যতীত অন্য কোনও অ্যারেতে পড়তে এর নামটি দিন। উদাহরণস্বরূপ, এটি অ্যারেতে পড়ে :< filename
filename
MAPFILE
lines
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/63
63
পরিবর্তে ব্যবহার করে আপনি বিকল্প প্রতিস্থাপনটি ভুলে যেতে পারেন বলে মনে করতে পারেন , তবে এটি কার্যকর হবে না কারণ যখন আপনার একাধিক কমান্ডের পাইপলাইন পৃথক করে আলাদা করা হয় , তখন ব্যাশ সাবশেলের সমস্ত কমান্ড চালায় । এইভাবে এবং উভয়ই তাদের নিজস্ব পরিবেশে চালিত হয় , আপনি যে পাইপলাইনটি চালান সেই শেলের পরিবেশ থেকে শুরু করে তবে পৃথক। সাবচেলে যেখানে সঞ্চালিত হয় সেখানে অ্যারেটি পপুলেশন হয় না , তবে কমান্ড শেষ হয়ে গেলে অ্যারেটি ফেলে দেওয়া হয়। কলারের জন্য কখনও তৈরি বা পরিবর্তিত হয় না।some-command arguments... | mapfile -t
|
some-command arguments...
mapfile -t
mapfile -t
MAPFILE
MAPFILE
এখানে কি উদাহরণ মধ্যে 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
। তবে এটির ক্ষেত্রেও এড়ানো উচিত যখন আপনি কেবল এটি কোনও কাজটি করতে পারে এমন কোনও আদেশের সাথে পাইপ করতে পারেন, যা বেশিরভাগ ক্ষেত্রে ।