বাশ: চলক লুপের শেষে ভেরিয়েবলের মান হারাবে


36

আমার শেল স্ক্রিপ্টগুলির একটিতে আমার সমস্যা আছে। কয়েকজন সহকর্মীকে জিজ্ঞাসা করলেন, তবে তারা সকলেই মাথা নেড়েছে (কিছু কিছু স্ক্র্যাচ করার পরে), তাই আমি এখানে একটি উত্তরের জন্য এসেছি।

আমার বোঝার অনুসারে নিম্নলিখিত শেল স্ক্রিপ্টটি শেষ লাইন হিসাবে "গণনা হয় 5" মুদ্রণ করা উচিত। এটি না করে বাদে। এটি "গণনাটি 0" মুদ্রণ করে। যদি "পড়া অবস্থায়" অন্য কোনও ধরণের লুপের সাথে প্রতিস্থাপন করা হয় তবে এটি ঠিক কাজ করে। লিপিটি এখানে:

প্রতিধ্বনি "1"> ইনপুট.ডাটা
প্রতিধ্বনি "2" >> ইনপুট.ডাটা
প্রতিধ্বনি "3" >> ইনপুট.ডাটা
প্রতিধ্বনি "4" >> ইনপুট.ডাটা
প্রতিধ্বনি "5" >> ইনপুট.ডাটা

CNT = 0 

বিড়াল ইনপুট.ডাটা | পড়ার সময়;
করা
  সিএনটি ++ দিন;
  প্রতিধ্বনি "গণনা $ সিএনটি"
সম্পন্ন 
প্রতিধ্বনি "গণনা $ সিএনটি"

কেন এটি ঘটে এবং আমি কীভাবে এটি প্রতিরোধ করতে পারি? আমি এটি ডেবিয়ান লেনি এবং স্কুজে চেষ্টা করেছি, একই ফলাফল (যেমন ব্যাশ ৩.২.৩৯ এবং ব্যাশ ৪.১.৫। আমি শেল স্ক্রিপ্ট উইজার্ড না হওয়ার জন্য পুরোপুরি স্বীকার করেছি, সুতরাং যে কোনও পয়েন্টারই প্রশংসা করবে।

উত্তর:


30

যুক্তি @ দেখুন # 24 ব্যাশ প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী এন্ট্রি: "আমি লুপ ভেরিয়েবল সেট কেন তারা হঠাৎ, লুপ বন্ধ পরে অদৃশ্য না বা কেন আমি নল ডেটা পড়তে পারবেন না।??" (অতি সম্প্রতি এখানে সংরক্ষণাগারভুক্ত )।

সংক্ষিপ্তসার: এটি কেবল ব্যাশ ৪.২ এবং তার থেকে উপরে সমর্থিত। আপনি যদি ব্যাশ ব্যবহার করে থাকেন তবে আপনাকে পাইপের পরিবর্তে কমান্ড বিকল্পের মতো বিভিন্ন উপায়ে ব্যবহার করতে হবে।


আপনি বোনাস পান, যেহেতু আপনার উত্তর আমাকে আরও বিস্তৃত বিকল্পগুলির সরবরাহ করেছিল।
ওল্ফগ্যাংসজ

5
লিঙ্কটি মারা গেছে। এই কারণেই লিংক-কেবল উত্তরগুলি খারাপ। কমপক্ষে এখানে সংক্ষিপ্তসার উত্তর দিন।
rudolfbyker

godশ্বর, আর একটি সময় যেখানে ksh কেবল আরও ভাল ... কেন, শুধু কেন সবাই বাশকে ঘিরে ধরে।
ফ্লোরিয়ান হিগল

@ ফ্লোরিয়ান হিগল: আপনি কি দাবি করছেন যে কেএসএই ওয়ান ট্রু শেল?
Ignacio Vazquez-

@ IgnacioVazquez- আব্রাম না, তবে আমি দাবি করি যে ব্যাশের সময় লুপ পরিচালনা করা ভয়াবহ পিআইটিএ। লুপ হ্যান্ডলিং 1993 এর কার্যকারিতা ধরা থেকে এড়াতে দীর্ঘ রানার ছিল। অন্যান্য জিনিসগুলি হ'ল হ'ল হ্যান্ডলিং যেখানে (এছাড়াও 1993) অন্তর্নির্মিত হ্যান্ডলারটি সহজ এবং সক্ষম ছিল, এমন কিছু যা আপনি এখনও ডকোপ্ট ব্যবহার না করে পেতে পারেন না। আমি দাবি করছি যে বাশ 20 বছরেরও বেশি সময় ধরে বাঁকটিকে পিছনে ফেলেছে, দৃistent়তার সাথে এবং এই এখানে বা মিলিয়ন লক্ষ লক্ষ খারাপ ব্যবহারের জন্য যে পরিমাণ সময় ব্যয় করা হয়েছে তা পরিমাপের বাইরে - কেবলমাত্র গ্রহণযোগ্য কারণ বেশিরভাগ মানুষ কখনই জানতে পারবে না।
ফ্লোরিয়ান হেইগল

30

এটি 'সাধারণ' ভুল। পাইপগুলি সাব-শেলগুলি তৈরি করে, তাই এটি while readআপনার স্ক্রিপ্টের চেয়ে আলাদা শেলের উপর চলছে, যা আপনার CNTপরিবর্তনশীলটিকে কখনই পরিবর্তন করে না (পাইপ সাবশেলের ভিতরে কেবলমাত্র))

এটি সংশোধন করার জন্য echoসাবশেলের সাথে সর্বশেষে গ্রুপ করুন while(এটি ঠিক করার আরও অনেক উপায় রয়েছে, এটি একটি I Iain এবং Ignacio এর উত্তরগুলির মধ্যে অন্যগুলি রয়েছে))

CNT=0

 cat input.data | ( while read 
do
  let CNT++;
  echo "Counting to $CNT"
done 
echo "Count is $CNT" )

দীর্ঘ ব্যাখ্যা:

  1. আপনি CNTআপনার স্ক্রিপ্টে মান 0 হিসাবে ঘোষণা করেন;
  2. একটি সাবশেল টুতে শুরু করা |হয়েছে while read;
  3. আপনার $CNTপরিবর্তনশীলটি 0 মান সহ সাবশলে রফতানি করা হয়েছে;
  4. সাবশেল গণনা করে CNTমানটি 5 তে বাড়িয়ে দেয় ;
  5. সাবশেল শেষ হয়, ভেরিয়েবল এবং মানগুলি ধ্বংস হয় (তারা কলিং প্রক্রিয়া / স্ক্রিপ্টে ফিরে আসে না)।
  6. আপনি echoআপনার মূল CNTমান 0।

2
আমি লিখেছিলাম প্রথম শেল লিপিটি আমাকে একই সমস্যাগুলি দিয়েছে, পাইপগুলি অতিরিক্ত শাঁস ছড়িয়ে দেয় তা খুঁজে পাওয়ার আগে কিছুক্ষণের জন্য আমার মাথাটি প্রাচীরের বিরুদ্ধে বেঁধে দেয়। আপনি পাইপটিতে যে কোনও ভেরিয়েবলের সাথে গোলমাল করবেন তা পাইপ শেষ হওয়ার সাথে সাথে সুযোগের বাইরে চলে যাবে - এর অর্থ হ'ল আপনি যদি সত্যই সত্যই পাইপটির বাইরের পরিবর্তে কিছু ব্যবহার করতে চান যেখানে এটি ব্যবহৃত হয়েছিল, আপনাকে অবশ্যই এটি করতে হবে একটি অস্থায়ী ফাইলের মতো মজাদার কিছু দিয়ে রাষ্ট্র ধরে রাখুন।
ফটোযুক্ত photo

দুর্দান্ত উত্তর, দুর্ভাগ্যক্রমে আমি কেবল একটি গ্রহণযোগ্যতা বোনাস দিতে পারি। দুঃখিত।
ওল্ফগ্যাংসজ

10

এইটা কাজ করে

CNT=0 

while read ;
do
  let CNT++;
  echo "Counting to $CNT"
done <input.data
echo "Count is $CNT"

আমি এটি পছন্দ করি, স্মার্ট উপায় কারণ আপনি জানেন যে প্রয়োজনীয় তথ্য কোথায় এবং কেবল এটির ফিরে পাওয়া দরকার। আপনি যদি উচ্চ দক্ষতার সমাধানগুলি জানেন না তবে আপনি সর্বদা "একটি ফাইল পড়তে" পারেন হাহাহাহাহা। আপনার জন্য +1
এম 3 এ

1
যে কেউ এটি পড়ছেন, সচেতন থাকুন যে আইনের সরবরাহিত সমাধানটি কেবল তখনই কাজ করবে যখন আপনি আপনার স্ক্রিপ্টটি স্পষ্টভাবে বাশকে অনুরোধ করবেন, প্রথম লাইনটি রেখে: #! / বিন / বাশ এবং এটি: #! / বিন / শ কাজ করবে না।
রোডওল

1
আকর্ষণীয়, প্রথম উদাহরণ আমি কখনই দেখেছি যেখানে বিড়ালের একটি অকেজো ব্যবহার আসলে কোডটি কাজ করা থেকে বিরত ছিল । @ রোডোওল দ্বারা, এখানে কেবলমাত্র বাশিজমই হ'ল লাইন let CNT++যা পরিবর্তে পসিক্স -কমপ্লায়েন্ট পাটিগণিত সম্প্রসারণেরCNT="$((CNT+1))" ব্যবহার করা উচিত । এটির বাকিগুলি ইতিমধ্যে পোর্টেবল।
ওয়াইল্ডকার্ড

6

পরিবর্তে উপ-শেলের মধ্যে ডেটা পাস করার চেষ্টা করুন, যেমন লুপ হওয়ার আগে এটি কোনও ফাইল। এটি লাইনগুলির সমাধানের মতো, তবে ধরে নেওয়া যায় আপনি কিছু বিরতিযুক্ত ফাইল চান না:

total=0
while read var
do
  echo "variable: $var"
  ((total+=var))
done < <(echo 45) #output from a command, script, or function
echo "total: $total"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.