$ '\ 0' '' এর মতো কেন?


10

কয়েকটি ফাইল দিয়ে জিনিসগুলি করার একটি সাধারণ উপায় হ'ল is এবং এর জন্য আমাকে আঘাত করবেন না:

for f in $(ls); do 

এখন, স্পেস বা অন্যান্য অদ্ভুত অক্ষরযুক্ত ফাইলগুলির বিরুদ্ধে সুরক্ষিত থাকার জন্য একটি সহজ উপায় হ'ল:

find . -type f -print0 | while IFS= read -r -d '' file; 

এখানে -d ''যেমন ASCII NUL সেট করার জন্য সংক্ষিপ্ত রয়েছে -d $'\0'

তবে কেন এমন হয়? কেন ''এবং $'\0'একই? এটি কি খালি স্ট্রিং সহ বাশের সি শিকড়গুলির কারণে সর্বদা নাল-সমাপ্ত হয়?


"সাদাসিধা" উপায় উল্লেখ করে, এই কাজ করার আরও ভাল উপায় আছে?
ইরুবার 12'13

2
যাইহোক, যদি আপনি ফাইলগুলির সেট দিয়ে পুনরায় ঘুরে বেড়ানো নিরাপদ অপারেশন করতে চান - for f in *পার্সিংয়ের পরিবর্তে ব্যবহার করুন ls

@ আমি জানি আমি for i in $(ls)ভয়াবহ বোকা — আমি প্রায় লজ্জিত আমি এটিকে এখানে খারাপ উদাহরণ হিসাবে ব্যবহার করেছি।
slhck

@ চন্দ্ররাভুরি হ্যাঁ, উদাহরণস্বরূপ find … -execফাইলগুলির চারপাশে লুপিংয়ের পরিবর্তে ব্যবহার করে, যা বেশিরভাগ ক্ষেত্রে কাজ করে যেখানে আপনি পরিবর্তে লুপ ব্যবহার করতে চান use এখানে, findআপনার জন্য সমস্ত কিছুর যত্ন নেয়।
slhck

@ স্লহ্যাক, ধন্যবাদ প্রতিটি ফাইলে মাল্টি-স্টেপ ক্রিয়াকলাপ জড়িত পরিস্থিতি সম্পর্কে কী যেখানে পঠনযোগ্যতার কারণে কোনও লুপ পছন্দনীয় হতে পারে? উপরের "ভীরু উপায়" এর চেয়ে ভাল লুপের বিকল্পটি কী আছে?
ইরুভর

উত্তর:


10

man page of bashলেখা আছে:

          -d delim
                 The first character of delim is  used  to  terminate  the
                 input line, rather than newline.

স্ট্রিংগুলি সাধারণত নাল টার্মিনেটেড হওয়ায় খালি স্ট্রিংয়ের প্রথম অক্ষর নাল বাইট হয়। - আমার কাছে যৌক্তিক. :)

সূত্রটি পড়ে:

static unsigned char delim;
[...]
    case 'd':
      delim = *list_optarg;
      break;

খালি স্ট্রিংয়ের delimজন্য কেবল নাল বাইট।


আপনি যখন বলেন "স্ট্রিংগুলি সাধারণত নাল টার্মিনেটেড হয়", তখন কি পসিক্স পরিবেশে কোথাও এটি হয় না ? যেদিন থেকে আমি স্কুলের জন্য সি শিখছিলাম, সেদিন থেকে অবশ্যই এটি ধরে নেওয়া বোধগম্য হয়; আমি খতিয়ে দেখছিলাম।
slhck

তবে যে কোনও স্ট্রিংকে যথেচ্ছভাবে অনেকগুলি খালি স্ট্রিং রয়েছে হিসাবে বিবেচনা করা যেতে পারে, যেমন আপনি যদি সম্মতিযুক্ত হন '' এবং 'এক্স' আপনি "এক্স" পান। সুতরাং আপনি তর্ক করতে পারেন যে প্রথম সাবস্ট্রিং বাশ মুখোমুখি হ'ল খালি স্ট্রিং। উদাহরণস্বরূপ আপনি যদি জাভাস্ক্রিপ্টের খালি স্ট্রিংটি ব্যবহার করেন তবে split()এটি প্রতিটি অক্ষরের মধ্যে বিভক্ত হবে। আমি সন্দেহ করি যে "historicalতিহাসিক কারণে" আমাদের পক্ষে সবচেয়ে ভাল ব্যাখ্যা হতে পারে।
donothingsuccessfully

ওয়েল, বেশ কারণ নয় "concatenating" একটি সি-শৈলী '\0'সঙ্গে 'X\0'আপনি দিতে হবে 'X\0', যদি সম্পন্ন ঠিক আছে। জাভাস্ক্রিপ্ট @ ডনের মতো ভাষাগুলিতে উচ্চ-স্তরের ফাংশনগুলির সাথে এর তেমন কিছু করার নেই
9:56 এ স্ল্যাক করুন

ধন্যবাদ, মিছাস, উত্স যোগ করার জন্য। delim = *list_optarg;এটি কেন সেভাবে তা পরিষ্কার করে দেয়।
slhck

@ এসএলএইচসি: দুঃখিত, আমি নিজেকে পরিষ্কার করে নিই না। আপনি "কেন ''এবং $'\0'একই?" জিজ্ঞাসা করেছিলেন , মিচাস "কোডটি তাই করে" এর প্রাকৃতিক ব্যাখ্যা দিয়েছেন। আমি খালি স্ট্রিং পরিচালনা করার বিকল্প পদ্ধতির রূপরেখাটি দেখলাম যা আমি সমান যুক্তিসঙ্গত দেখলাম এবং পরামর্শ দিয়েছিলাম যে একটি বা অন্যকে বেছে নেওয়া কেবল কনভেনশন বা ঘটনার বিষয়।
donothingsuccessfully

6

বাশের দুটি ঘাটতি রয়েছে যা একে অপরকে ক্ষতিপূরণ দেয়।

আপনি যখন লেখেন $'\0', খালি স্ট্রিংয়ের সাথে এটি অভ্যন্তরীণভাবে অভিন্নরূপে চিকিত্সা করা হয়। উদাহরণ স্বরূপ:

$ a=$'\0'; echo ${#a}
0

এর কারণ অভ্যন্তরীণভাবে বাশ সমস্ত স্ট্রিং সি স্ট্রিং হিসাবে সঞ্চয় করে, যা নাল-সমাপ্ত - একটি নাল বাইট স্ট্রিংয়ের শেষে চিহ্নিত করে। বাশ নিঃশব্দে প্রথম নাল বাইটে স্ট্রিংটি কেটে দেয় (যা স্ট্রিংয়ের অংশ নয়!)।

# a=$'foo\0bar'; echo "$a"; echo ${#a}
foo
3

যখন আপনি বিল্টিনের -dবিকল্পের জন্য একটি আর্গুমেন্ট হিসাবে একটি স্ট্রিং পাস করেন read, বাশ কেবল স্ট্রিংয়ের প্রথম বাইটটি দেখায়। তবে এটি আসলে পরীক্ষা করে না যে স্ট্রিংটি খালি নেই not অভ্যন্তরীণভাবে, একটি খালি স্ট্রিংটি 1-উপাদান বাইট অ্যারে হিসাবে উপস্থাপিত হয় যেখানে কেবল নাল বাইট থাকে। সুতরাং স্ট্রিংয়ের প্রথম বাইটটি পড়ার পরিবর্তে বাশ এই নাল বাইটটি পড়ে।

তারপরে, অভ্যন্তরীণভাবে, readবিল্টিনের পিছনের যন্ত্রপাতিগুলি নাল বাইটগুলির সাথে ভালভাবে কাজ করে; এটি ডিলিমেটারটি না পাওয়া পর্যন্ত এটি বাইট বাই পড়া চালিয়ে যায়।

অন্যান্য শাঁস আলাদা আচরণ করে। উদাহরণস্বরূপ, ছাই এবং ksh নাল বাইট উপেক্ষা করে যখন তারা ইনপুট পড়ে। Ksh সহ, ksh -d ""একটি নতুন লাইন পর্যন্ত পড়া। শেলগুলি বাইনারি ডেটা দিয়ে নয়, পাঠ্যের সাথে ভালভাবে মোকাবেলার জন্য ডিজাইন করা হয়েছে। জেডএস একটি ব্যতিক্রম: এটি একটি স্ট্রিং প্রতিনিধিত্ব ব্যবহার করে যা নাল বাইটগুলি সহ স্বেচ্ছাসেবী বাইটগুলি সহ অনুলিপি করে; zsh এ, $'\0'দৈর্ঘ্যের 1 টি স্ট্রিং (তবে read -d '', অদ্ভুতভাবে, এর মতো আচরণ করে read -d $'\0')।


আচরণকে readব্যাশ 4.3 পরিবর্তন যাতে এটি এখন নাল বাইট অগ্রাহ্য। উদাহরণস্বরূপ পরিবর্তে read x< <(printf a\\0a)সেট xকরে । aaa
ল্রি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.