আমি কীভাবে ব্যাশে নাল বাইট ব্যবহার করব?


33

আমি পড়েছি যেহেতু বাশের ফাইল-পাথগুলিতে নাল বাইট (শূন্য-মূল্যবান বাইট, $'\0') ব্যতীত অন্য কোনও অক্ষর থাকতে পারে , নাল বাইটকে বিভাজক হিসাবে ব্যবহার করা ভাল। উদাহরণস্বরূপ, যদি এর আউটপুট findঅন্য কোনও প্রোগ্রামে প্রেরণ করা হয়, তবে -print0বিকল্পটি ( findএটির সংস্করণগুলির জন্য ) ব্যবহার করার পরামর্শ দেওয়া হচ্ছে ।

তবে যদিও এর মতো কিছু সূক্ষ্মভাবে কাজ করে (নতুন লাইনের দ্বারা পৃথক করা ফাইল-পাথগুলি মুদ্রণ করা - চিন্তা করবেন না, এটি কেবল একটি প্রদর্শনী, আমি আসলে এটি বাস্তব স্ক্রিপ্টগুলিতে করছি না):

find -print0 \
  | while IFS= read -r -d $'\0' ; do echo "$REPLY" ; done

এর মতো কিছু কাজ করে না :

for file in * ; do echo -n "$file"$'\0' ; done \
  | while IFS= read -r -d $'\0' ; do echo "$REPLY" ; done

আমি যখন কেবলমাত্র- forলুপ অংশটি চেষ্টা করি তখন দেখতে পাচ্ছি যে এটি সমস্ত ফাইলের নামগুলি একসাথে মুদ্রণ করে, এর মধ্যে নাল বাইট ছাড়াই

কেন? কি হচ্ছে?

উত্তর:


43

বাশ অভ্যন্তরীণভাবে সি-স্টাইলের স্ট্রিং ব্যবহার করে, যা নাল বাইট দ্বারা সমাপ্ত হয়। এর অর্থ হ'ল বাশ স্ট্রিং (যেমন কোনও ভেরিয়েবলের মান, বা কমান্ডের যুক্তি) আসলে কোনও নাল বাইট থাকতে পারে না। উদাহরণস্বরূপ, এই মিনি লিপি:

foobar=$'foo\0bar'    # foobar='foo' + null byte + 'bar'
echo "${#foobar}"     # print length of $foobar

প্রকৃতপক্ষে প্রিন্ট করে 3, কারণ $foobarএটি আসলে ন্যায় 'foo': barস্ট্রিংয়ের শেষে আসে after

একইভাবে, echo $'foo\0bar'শুধু মুদ্রণ foo, কারণ অংশ echoসম্পর্কে জানেন না \0bar

আপনি দেখতে পাচ্ছেন, \0ক্রমটি আসলে একটি $'...'স্টাইলের স্ট্রিংয়ে খুব বিভ্রান্তিকর ; এটি স্ট্রিংয়ের ভিতরে নাল বাইটের মতো দেখায় তবে এটি সেইভাবে কাজ করে না। আপনার প্রথম উদাহরণে, আপনার readআদেশ আছে -d $'\0'। এটি কাজ করে, তবে কেবল কারণেই -d ''কাজ করে! (এটি কোনও স্পষ্টভাবে নথিভুক্ত বৈশিষ্ট্য readনয়, তবে আমি মনে করি এটি একই কারণে কাজ করে: ''খালি স্ট্রিং, তাই এটির সমাপ্তি নাল বাইট অবিলম্বে আসে " " ডিলিমের প্রথম চরিত্র "ব্যবহার করে নথিভুক্ত করা হয়েছে , এবং আমি অনুমান করি যে এটি এমনকি কাজ করে যদি "প্রথম অক্ষর" স্ট্রিংয়ের শেষের পরে চলে যায়!)-d delim

তবে আপনি যেমন নিজের findউদাহরণ থেকে জানেন , কোনও কমান্ডের দ্বারা নাল বাইট প্রিন্ট করা সম্ভব হয় এবং সেই বাইটের জন্য অন্য কোনও কমান্ডে পাইপ দেওয়া হয় যা এটিকে ইনপুট হিসাবে পড়ে। এর কোনও অংশই বাশের অভ্যন্তরে স্ট্রিংয়ে নাল বাইট সংরক্ষণ করার উপর নির্ভর করে না । আপনার দ্বিতীয় উদাহরণটির সাথে একমাত্র সমস্যাটি হ'ল আমরা $'\0'কোনও আদেশের যুক্তিতে ব্যবহার করতে পারি না ; echo "$file"$'\0'আনন্দের সাথে শেষে নাল বাইটটি প্রিন্ট করতে পারে, কেবল যদি এটি জানত যে আপনি এটি চাইছেন।

সুতরাং ব্যবহারের পরিবর্তে echo, আপনি ব্যবহার করতে পারেন printf, যা $'...'স্টাইল স্ট্রিংয়ের মতো একই ধরণের অব্যাহতি সিকোয়েন্সগুলিকে সমর্থন করে । এইভাবে, আপনি স্ট্রিংয়ের ভিতরে নাল বাইট না রেখে নাল বাইট মুদ্রণ করতে পারেন। এটি দেখতে এই রকম হবে:

for file in * ; do printf '%s\0' "$file" ; done \
  | while IFS= read -r -d '' ; do echo "$REPLY" ; done

বা কেবল এটি:

printf '%s\0' * \
  | while IFS= read -r -d '' ; do echo "$REPLY" ; done

(দ্রষ্টব্য: echoপ্রকৃতপক্ষে একটি -eপতাকাও রয়েছে যা এটি \0নাল বাইট প্রসেস করতে এবং প্রিন্ট করতে দেয় ; তবে এটি আপনার ফাইলের নামটিতে কোনও বিশেষ সিকোয়েন্সগুলি প্রক্রিয়া করার চেষ্টাও করে। সুতরাং printfপদ্ধতির ব্যবস্থাটি আরও দৃ )়)


উল্লেখ্য, কিছু শাঁস যে কি নাল ভিতরে স্ট্রিং বাইট অনুমতি দেয়। আপনার উদাহরণটি Zsh এ সূক্ষ্মভাবে কাজ করে, উদাহরণস্বরূপ (ডিফল্ট সেটিংস অনুমান করে)। তবে, আপনার শেল নির্বিশেষে, ইউনিক্স-এর মতো অপারেটিং সিস্টেমগুলি প্রোগ্রামগুলিতে আর্গুমেন্টের মধ্যে নাল বাইট অন্তর্ভুক্ত করার উপায় সরবরাহ করে না (যেহেতু প্রোগ্রাম আর্গুমেন্টগুলি সি-স্টাইলের স্ট্রিং হিসাবে পাস করা হয়), তাই সর্বদা কিছু সীমাবদ্ধতা থাকবে। (আপনার উদাহরণটি কেবল ঝেশে কাজ করতে পারে কারণ echoএটি একটি শেল অন্তর্নির্মিত, তাই অন্য প্রোগ্রামগুলিকে আহ্বান করার জন্য ওএস সাপোর্টের উপর নির্ভর না করে Zsh এটিকে প্রার্থনা করতে পারে you আপনি যদি এর command echoপরিবর্তে ব্যবহার করেন echo, যাতে এটি বিল্টিনকে ছাড়িয়ে যায় এবং স্ট্যান্ডএলোন echoপ্রোগ্রামটি ব্যবহার করে $PATH, আপনি বাশের মতো জেডসে একই আচরণ দেখতে পাবেন))


2
-d ''ইতিমধ্যে সীমানা ছাড়াই যদি আইএফএসকে কিছুতেই সেট করা হয় না \0? : আমি এখানে একটি ব্যাখ্যা পাওয়া stackoverflow.com/questions/8677546/...
CMCDragonkai
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.