ফাংশনগুলিতে কেন একটি সম্পূর্ণ বাশ স্ক্রিপ্ট লিখুন?


59

কর্মক্ষেত্রে, আমি ঘন ঘন ব্যাশ স্ক্রিপ্টগুলি লিখি। আমার তত্ত্বাবধায়ক নীচের উদাহরণের মতো পুরো স্ক্রিপ্টটি ফাংশনে বিভক্ত করার পরামর্শ দিয়েছেন:

#!/bin/bash

# Configure variables
declare_variables() {
    noun=geese
    count=three
}

# Announce something
i_am_foo() {
    echo "I am foo"
    sleep 0.5
    echo "hear me roar!"
}

# Tell a joke
walk_into_bar() {
    echo "So these ${count} ${noun} walk into a bar..."
}

# Emulate a pendulum clock for a bit
do_baz() {
    for i in {1..6}; do
        expr $i % 2 >/dev/null && echo "tick" || echo "tock"
        sleep 1
    done
}

# Establish run order
main() {
    declare_variables
    i_am_foo
    walk_into_bar
    do_baz
}

main

"পাঠযোগ্যতা" ব্যতীত এগুলি করার কি কোনও কারণ আছে, যা আমি মনে করি আরও কয়েকটি মন্তব্য এবং কিছু লাইন ফাঁক দিয়ে সমানভাবে প্রতিষ্ঠিত হতে পারে?

এটি কী স্ক্রিপ্টটিকে আরও দক্ষতার সাথে চালিত করে (আমি আসলে বিপরীতটি আশা করি, যদি কিছু থাকে), বা এটি পূর্বে বর্ণিত পাঠযোগ্যতার সম্ভাবনার বাইরে কোডটি সংশোধন করা সহজ করে তোলে? বা এটি কি কেবল একটি স্টাইলিস্টিক পছন্দ?

দয়া করে মনে রাখবেন যে স্ক্রিপ্টটি এটি ভালভাবে প্রদর্শন করে না, আমাদের প্রকৃত স্ক্রিপ্টগুলিতে ফাংশনগুলির "রান অর্ডার" খুব লিনিয়ার হতে পারে - walk_into_barযা i_am_fooকরা জিনিসগুলির উপর নির্ভর করে এবং do_bazসেট আপ করা স্টাফগুলিতে কাজ করে walk_into_bar- তাই হচ্ছে রান অর্ডারকে ইচ্ছামত অদলবদল করতে সক্ষম এমন কিছু নয় যা আমরা সাধারণত করতাম। উদাহরণস্বরূপ, আপনি হঠাৎ declare_variablesপরে walk_into_barএটি স্থাপন করতে চান না , এটি জিনিসগুলি ভেঙে দেবে।

আমি উপরের লিপিটি কীভাবে লিখব তার একটি উদাহরণ হ'ল:

#!/bin/bash

# Configure variables
noun=geese
count=three

# Announce something
echo "I am foo"
sleep 0.5
echo "hear me roar!"

# Tell a joke
echo "So these ${count} ${noun} walk into a bar..."

# Emulate a pendulum clock for a bit
for i in {1..6}; do
    expr $i % 2 >/dev/null && echo "tick" || echo "tock"
    sleep 1
done

30
আমি তোমার বস পছন্দ করি আমার স্ক্রিপ্টগুলিতে আমি main()শীর্ষে রেখেছি এবং main "$@"নীচে এটি কল করতে যুক্ত করব। এটি যখন আপনি এটি খুলবেন তখন আপনাকে উচ্চ স্তরের স্ক্রিপ্ট যুক্তি প্রথম দেখায়।
জন কুগেলম্যান

22
পাঠযোগ্যতা "আরও কয়েকটি মন্তব্য এবং কিছু লাইন ফাঁক দিয়ে সমানভাবে প্রতিষ্ঠিত হতে পারে" এই ধারণার সাথে আমি একমত নই। কল্পকাহিনী ছাড়াও, আমি এমন কোনও বইয়ের সাথে ডিল করতে চাই না যাতে প্রতিটি অধ্যায় এবং বিভাগের জন্য সামগ্রীর সারণী এবং বর্ণনামূলক নাম নেই। প্রোগ্রামিং ভাষাগুলিতে, এটি ফাংশনগুলি সরবরাহ করতে পারে এমন ধরনের পাঠযোগ্যতা, এবং মন্তব্য করা যায় না।
রাইময়েড

6
নোট করুন যে ফাংশনগুলিতে ঘোষিত ভেরিয়েবলগুলি ঘোষণা করা উচিত local- এটি ভেরিয়েবল স্কোপ সরবরাহ করে যা কোনও তুচ্ছ স্ক্রিপ্টে অবিশ্বাস্যভাবে গুরুত্বপূর্ণ।
বোরিস স্পাইডার

8
আমি আপনার বসের সাথে একমত নই। আপনার স্ক্রিপ্টটি যদি ফাংশনগুলিতে বিভক্ত করতে হয় তবে আপনার প্রথম দিকে শেল স্ক্রিপ্টটি লেখা উচিত নয়। পরিবর্তে একটি প্রোগ্রাম লিখুন।
el.pescado

6
ফাংশনগুলি এমন প্রক্রিয়াগুলির জন্য যা পুনরাবৃত্তি হয়, স্ক্রিপ্টের মধ্যে বা একাধিক স্ক্রিপ্টে। তারা অভিন্ন পদ্ধতিগুলি স্থাপনের অনুমতি দেয়। উদাহরণস্বরূপ syslog লিখতে একটি ফাংশন ব্যবহার করে। যতক্ষণ না প্রত্যেকে একই ফাংশনটি ব্যবহার করে, ততক্ষণ আপনার সিসলগ এন্ট্রি আরও সামঞ্জস্যপূর্ণ। আপনার উদাহরণের মতো একক ব্যবহারের ফাংশন অযথা স্ক্রিপ্ট জটিল করে তোলে। কিছু ক্ষেত্রে, তারা সমস্যাগুলি (ভেরিয়েবল স্কোপিং) প্রবর্তন করে।
Xalorous

উত্তর:


39

আমি পড়ার পর ব্যাশ প্রোগ্রামিং এই একই শৈলী ব্যবহার শুরু করেছি Kfir Lavi এর ব্লগ পোস্টে "ডিফেন্সিভ ব্যাশ প্রোগ্রামিং" । তিনি বেশ কয়েকটি ভাল কারণ দিয়েছেন তবে ব্যক্তিগতভাবে আমি এগুলিকে সবচেয়ে গুরুত্বপূর্ণ বলে মনে করি:

  • পদ্ধতিগুলি বর্ণনামূলক হয়ে ওঠে: কোডের একটি বিশেষ অংশটি কী করণীয় তা নির্ধারণ করা অনেক সহজ। কোডের দেওয়ালের পরিবর্তে, আপনি "ওহ, find_log_errorsফাংশনটি ত্রুটির জন্য সেই লগ ফাইলটি পড়ে" দেখুন। Useশ্বরকে ব্যবহার করে এমন পুরো অবধি / গ্রেপ / সেড লাইনের সন্ধানের সাথে এর সাথে তুলনা করুন যে একটি দীর্ঘ স্ক্রিপ্টের মাঝখানে কী ধরণের রেজেক্স জানে - আপনি মন্তব্য করেন না তবে সেখানে কী করছে তা আপনার ধারণা নেই।

  • আপনি set -xএবং এটিকে ঘিরে ফাংশনগুলি ডিবাগ করতে পারেন set +x। আপনি যদি জানতে পারেন যে বাকী কোডটি ঠিকঠাকভাবে কাজ করে, আপনি কেবল সেই নির্দিষ্ট ফাংশনটি ডিবাগিংয়ে ফোকাস করার জন্য এই কৌশলটি ব্যবহার করতে পারেন। অবশ্যই, আপনি স্ক্রিপ্টের কিছু অংশ বন্ধ করতে পারেন, তবে এটি যদি দীর্ঘ অংশ হয়? এটির মতো কিছু করা সহজ:

     set -x
     parse_process_list
     set +x
  • সঙ্গে মুদ্রণ ব্যবহার cat <<- EOF . . . EOF। আমি আমার কোডটিকে আরও বেশি পেশাদার করতে এটি বেশ কয়েকবার ব্যবহার করেছি। এছাড়াও, ফাংশন parse_args()সহ getoptsবেশ সুবিধাজনক। আবার, এটি পাঠ্যের দৈত্য প্রাচীর হিসাবে স্ক্রিপ্টে সবকিছু মুছে ফেলার পরিবর্তে পাঠযোগ্যতার সাথে সহায়তা করে। এগুলি পুনরায় ব্যবহার করাও সুবিধাজনক।

এবং স্পষ্টতই, এটি সি বা জাভা বা ভালা জানে এমন ব্যক্তির পক্ষে অনেক বেশি পাঠযোগ্য, তবে বাশের অভিজ্ঞতা সীমিত। দক্ষতা যতদূর যায়, আপনি যা করতে পারেন তা তেমন কিছু নেই - বাশ নিজেই সবচেয়ে কার্যকর ভাষা নয় এবং গতি এবং দক্ষতার বিষয়টি যখন আসে তখন লোকেরা পার্ল এবং অজগর পছন্দ করে। তবে, আপনি niceএকটি ফাংশন করতে পারেন :

nice -10 resource_hungry_function

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

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

আমি এই স্টাইলটি যেখানে ব্যবহার করেছি তার কয়েকটি উদাহরণ:


3
আমি নিশ্চিত নই যে আপনার নিবন্ধটি থেকে খুব গুরুত্ব সহকারে কোনও পরামর্শ নেওয়া উচিত। মঞ্জুর, এটিতে বেশ কয়েকটি ভাল ধারণা রয়েছে তবে এটি স্পষ্টতই নয় যে কেউ স্ক্রিপ্টিং শেল ব্যবহার করেন। নেই একটি একক উদাহরণ কোনো পরিবর্তনশীল উদ্ধৃত করা হয় (!) এবং এটা বড় হাতের পরিবর্তনশীল নামের যা প্রায়ই একটি খুব খারাপ ধারণা যেহেতু তারা বিদ্যমান env Vars সঙ্গে বিরোধ সৃষ্টি করতে পারে ব্যবহার দাড়ায়। এই উত্তরের আপনার বক্তব্যগুলি অর্থবোধ করে, তবে লিঙ্কিত নিবন্ধটি এমন কেউ লিখেছেন যা কেবলমাত্র অন্য ভাষার জন্য ব্যবহৃত এবং সেগুলি স্ট্যাশকে জোর করে চাপিয়ে দেওয়ার চেষ্টা করছে।
টেরডন

1
@terdon আমি নিবন্ধটিতে ফিরে গিয়ে এটি আবার পড়ি। লেখক কেবলমাত্র স্থান যেখানে পরিবর্তনশীল নামকরণ উল্লেখ করেছেন "অপরিবর্তনীয় গ্লোবাল ভেরিয়েবলস" এ। আপনি যদি বিশ্বব্যাপী ভেরিয়েবলগুলি ফাংশনের পরিবেশের মধ্যে থাকা হিসাবে বিবেচনা করেন, তবে সেগুলি মূলধন করার জন্য এটি অর্থবোধ করে। পাশের নোটে, বাশের ম্যানুয়ালটি চলক ক্ষেত্রে কনভেনশন নির্দেশ করে না। এমনকি এখানে স্বীকৃত উত্তর বলেছে "সাধারণত" এবং একমাত্র "মান" গুগল, যা পুরো আইটি শিল্পের প্রতিনিধিত্ব করে না।
সের্গেই কলডিয়াজনি

আরেকটি নোটের বিষয়ে অটার্ডন, আমি 100% এর সাথে সম্মত হই যে পরিবর্তনশীল উদ্ধৃতিটি নিবন্ধে উল্লেখ করা উচিত ছিল এবং এটি ব্লগে দেওয়া মন্তব্যেও উল্লেখ করা হয়েছে। এছাড়াও, আমি অন্য কোনও ভাষাতে অভ্যস্ত কিনা তা বিবেচনা না করেই এই কোডিংয়ের স্টাইলটি ব্যবহার করে কেউ বিচার করব না। এই পুরো প্রশ্ন এবং উত্তরগুলি এর সুবিধাগুলি স্পষ্টভাবে দেখায় এবং ব্যক্তির ডিগ্রি যার সাথে তারা অন্য ভাষায় ব্যবহৃত হয় সম্ভবত এখানে অপ্রাসঙ্গিক।
সের্গেই কলডিয়াজনি

1
@ ইটারডন ভাল, নিবন্ধটি "উত্স" উপাদানের অংশ হিসাবে পোস্ট করা হয়েছিল। আমি সমস্ত কিছু নিজের মতামত হিসাবে পোস্ট করতে পারতাম, তবে আমাকে কেবল কৃতিত্ব দিতে হয়েছিল যে আমি নিবন্ধ থেকে কিছু জিনিস শিখেছি এবং এটিই সময়ের সাথে সাথে গবেষণা থেকে এসেছে। লেখকের লিঙ্কডিন পৃষ্ঠাটি দেখায় যে তারা লিনাক্স এবং আইটি-র সাথে সাধারণভাবে ভাল অভিজ্ঞতা রয়েছে, সুতরাং আমি অনুমান করতে পারি যে নিবন্ধটি সত্যিই এটি দেখায় না, তবে লিনাক্স এবং শেল স্ক্রিপ্টিংয়ের ক্ষেত্রে আপনার অভিজ্ঞতার উপর আমি ভরসা রাখি যাতে আপনি সঠিক হতে পারেন ।
সের্গেই কোলোডিয়াজনি

1
এটি একটি দুর্দান্ত উত্তর তবে আমি বাশের যে পরিবর্তনশীল সুযোগটি মজাদার তা যুক্ত করতে চাই। যে কারণে, আমি ফাংশনের localমাধ্যমে সমস্ত কিছু ব্যবহার করে এবং কল করে ফাংশনের অভ্যন্তরে আমার ভেরিয়েবলগুলি ঘোষণা করতে পছন্দ করি main()। এটি জিনিসগুলিকে অনেক বেশি পরিচালনাযোগ্য করে তোলে এবং আপনি সম্ভাব্য নোংরা পরিস্থিতি এড়াতে পারেন।
হউসনি

65

পঠনযোগ্যতা একটি জিনিস। তবে কেবল এটার চেয়ে মডুলারাইজেশনের আরও অনেক কিছু আছে । ( ফাংশনগুলির জন্য আধা-মডুলারাইজেশন সম্ভবত আরও সঠিক)

ফাংশনগুলিতে আপনি স্থানীয় কিছু ভেরিয়েবল রাখতে পারেন যা নির্ভরযোগ্যতা বাড়ে , জিনিসগুলি নষ্ট হওয়ার সম্ভাবনা হ্রাস করে।

ফাংশন আরেকটি প্রো হয় পুনরায় ব্যবহারযোগ্যতা । একবার কোনও ফাংশন কোডিং হয়ে গেলে, এটি স্ক্রিপ্টে একাধিকবার প্রয়োগ করা যেতে পারে। আপনি এটি অন্য স্ক্রিপ্টেও পোর্ট করতে পারেন।

আপনার কোডটি এখন রৈখিক হতে পারে তবে ভবিষ্যতে আপনি বাশ বিশ্বে মাল্টি-থ্রেডিং বা মাল্টি-প্রসেসিংয়ের রাজ্যে প্রবেশ করতে পারেন । একবার আপনি ফাংশনে জিনিসগুলি শিখতে গেলে, সমান্তরালে পদক্ষেপের জন্য আপনি ভালভাবে সজ্জিত হবেন।

যোগ করার জন্য আরও একটি পয়েন্ট। নীচের মন্তব্যে এএসিটপাব নিওলিভ লক্ষ্য করেছেন, সুসংগত সত্তা হিসাবে ফাংশন থেকে পুনঃনির্দেশ করা সহজ। তবে ফাংশনগুলির সাথে পুনর্নির্দেশগুলির আরও একটি দিক রয়েছে। যথা, ফাংশন সংজ্ঞা পাশাপাশি পুনর্নির্দেশগুলি সেট করা যেতে পারে। যেমন .:

f () { echo something; } > log

ফাংশন কলগুলির দ্বারা এখন কোনও স্পষ্টত পুনঃনির্দেশের প্রয়োজন নেই।

$ f

এটি অনেকগুলি পুনরাবৃত্তি বাড়াতে পারে, যা আবার নির্ভরযোগ্যতা বৃদ্ধি করে এবং জিনিসগুলিকে যথাযথ রাখতে সহায়তা করে।

আরো দেখুন


55
খুব ভাল উত্তর যদিও এটি ফাংশনে বিভক্ত হয়ে থাকলে এটি আরও ভাল।
পিয়ের আরলাড

1
সম্ভবত যুক্ত করুন যে ফাংশনগুলি আপনাকে সেই স্ক্রিপ্টটিকে অন্য স্ক্রিপ্টে আমদানি করার অনুমতি দেয় (ব্যবহার করে sourceবা . scriptname.shএই ফাংশনগুলি যেমন আপনার নতুন স্ক্রিপ্টে থাকে
তেমন ব্যবহার করুন

এটি ইতিমধ্যে অন্য উত্তরে coveredাকা রয়েছে।
টমাসজ

1
আমি ওটার তারিফ করি. তবে আমি বরং অন্য লোকদেরও গুরুত্বপূর্ণ হতে দিতাম।
টমাসজ

7
আমি আজ একটি মামলার মুখোমুখি হয়েছি যেখানে আমাকে স্ক্রিপ্টের কিছু আউটপুট প্রতিধ্বনির পরিবর্তে কোনও ফাইলে (ইমেলের মাধ্যমে প্রেরণে) পাঠাতে হয়েছিল। কাঙ্ক্ষিত ফাংশনগুলির আউটপুটটিকে পুনর্নির্দেশ করতে আমার কেবল মাই ফাংশন >> মাইফাইল করতে হয়েছিল। খুব সুবিধাজনক। প্রাসঙ্গিক হতে পারে।
এএসিটপাব নিওলিভ

39

আমার মন্তব্যে, আমি কার্যকারিতাগুলির তিনটি সুবিধা উল্লেখ করেছি:

  1. তারা সঠিকতা পরীক্ষা এবং যাচাই করা সহজ।

  2. ভবিষ্যতের স্ক্রিপ্টগুলিতে ফাংশনগুলি সহজেই পুনরায় ব্যবহার করা যেতে পারে (উত্সাহিত)

  3. আপনার বস তাদের পছন্দ করে।

এবং, 3 নম্বরের গুরুত্বকে কখনই হ্রাস করবেন না।

আমি আরও একটি ইস্যু সম্বোধন করতে চাই:

... সুতরাং রান অর্ডারকে যথেচ্ছভাবে অদলবদল করতে সক্ষম হওয়া এমন কিছু নয় যা আমরা সাধারণত করতাম। উদাহরণস্বরূপ, আপনি হঠাৎ declare_variablesপরে walk_into_barএটি স্থাপন করতে চান না , এটি জিনিসগুলি ভেঙে দেবে।

কার্যগুলিতে কোড ভাঙার সুবিধা পেতে, কারওটিকে যথাসম্ভব স্বতন্ত্র করার চেষ্টা করা উচিত। যদি walk_into_barএমন কোনও ভেরিয়েবলের প্রয়োজন হয় যা অন্য কোথাও ব্যবহার করা হয় না, তবে সেই পরিবর্তনশীলটি সংজ্ঞায়িত করা উচিত এবং এর সাথে স্থানীয় করা উচিত walk_into_bar। কোডগুলিকে ফাংশনগুলিতে আলাদা করার এবং তাদের আন্তঃনির্ভরশীলতা হ্রাস করার প্রক্রিয়াটি কোডটিকে আরও পরিষ্কার এবং সহজ করে তুলবে।

আদর্শভাবে, ফাংশনগুলি স্বতন্ত্রভাবে পরীক্ষা করা সহজ হওয়া উচিত। যদি, মিথস্ক্রিয়াগুলির কারণে, তাদের পরীক্ষা করা সহজ হয় না, তবে এটি একটি চিহ্ন যে তারা পুনর্নির্মাণের মাধ্যমে উপকৃত হতে পারে।


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

4
ফাংশনগুলিতে যা ভাগ করা দরকার তা হওয়া উচিত, তবে উদাহরণটি এটিকে অনেক দূরে নিয়ে যায়। আমি মনে করি যে কেবলমাত্র সত্য যে আমাকে বাগ দেয় তা হ'ল ভেরিয়েবল ডিক্লেয়ারেশন ফাংশন। গ্লোবাল ভেরিয়েবলগুলি, বিশেষত স্থিতিশীলগুলি, সেই উদ্দেশ্যে উত্সর্গীকৃত একটি মন্তব্য বিভাগে বিশ্বব্যাপী সংজ্ঞায়িত করা উচিত। গতিশীল ভেরিয়েবলগুলি যে ফাংশনগুলি ব্যবহার করে এবং তাদের সংশোধন করে তার জন্য স্থানীয় হওয়া উচিত।
Xalorous

@ ক্যালরাস আমি এমন একটি অনুশীলন দেখেছি যেখানে গ্লোবাল ভেরিয়েবলগুলি কোনও পদ্ধতিতে সূচনা করা হয়, কোনও প্রক্রিয়া বিকাশের আগে একটি মধ্যবর্তী এবং দ্রুত পদক্ষেপ হিসাবে যা কোনও বাহ্যিক ফাইল থেকে তাদের মান পড়ে ... আমি সম্মত হই যে এটি আলাদা সংজ্ঞা এবং আরও পরিষ্কার হওয়া উচিত সূচনা কিন্তু খুব কমই আপনাকে সুবিধা নম্বর 3 এ যেতে হবে;-)
হাস্তুর

13

আপনি সি / সি ++, পাইথন, পার্ল, রুবি বা যে কোনও প্রোগ্রামিং ল্যাঙ্গুয়েজ কোড হিসাবে যে কাজটি করেন সেই একই কারণে আপনি কোডগুলি ফাংশনে বিভক্ত করেন। গভীর কারণটি বিমূর্ততা - আপনি নিম্ন স্তরের কাজগুলিকে উচ্চ স্তরের আদিম (ফাংশন )গুলিতে সজ্জিত করেন যাতে জিনিসগুলি কীভাবে করা হয় সে সম্পর্কে আপনার মাথা ঘামানোর দরকার নেই। একই সময়ে, কোডটি আরও পঠনযোগ্য (এবং রক্ষণাবেক্ষণযোগ্য) হয়ে যায় এবং প্রোগ্রামের যুক্তি আরও স্পষ্ট হয়ে যায়।

যাইহোক, আপনার কোডটি দেখে আমি ভেরিয়েবলগুলি ঘোষণার জন্য কোনও ফাংশন পাওয়া বেশ অদ্ভুত বলে মনে করি; এটি সত্যই আমাকে চোখের পাতায় উঠিয়ে তোলে।


আন্ডাররেটেড উত্তর আইএমএইচও। আপনি কি তখন mainফাংশন / পদ্ধতিতে ভেরিয়েবলগুলি ঘোষণার পরামর্শ দিচ্ছেন ?
ডেভিড তাবারনারো এম।

12

যদিও আমি সম্পূর্ণই সাথে একমত পুনর্ব্যাবহার্যোগ্যতা , পাঠযোগ্যতা , এবং delicately, নেতাদের চুম্বন কিন্তু সেখানে ফাংশন অন্য একটি সুবিধা : পরিবর্তনশীল সুযোগএলডিপি যেমন দেখায় :

#!/bin/bash
# ex62.sh: Global and local variables inside a function.

func ()
{
  local loc_var=23       # Declared as local variable.
  echo                   # Uses the 'local' builtin.
  echo "\"loc_var\" in function = $loc_var"
  global_var=999         # Not declared as local.
                         # Therefore, defaults to global. 
  echo "\"global_var\" in function = $global_var"
}  

func

# Now, to see if local variable "loc_var" exists outside the function.

echo
echo "\"loc_var\" outside function = $loc_var"
                                      # $loc_var outside function = 
                                      # No, $loc_var not visible globally.
echo "\"global_var\" outside function = $global_var"
                                      # $global_var outside function = 999
                                      # $global_var is visible globally.
echo                      

exit 0
#  In contrast to C, a Bash variable declared inside a function
#+ is local ONLY if declared as such.

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

পুনরায় ব্যবহারযোগ্যতার অর্থ প্রায়শই ফাংশনগুলির একটি সাধারণ গ্রন্থাগার তৈরি sourceকরা এবং আপনার সমস্ত স্ক্রিপ্টগুলিতে সেই লাইব্রেরিটি যুক্ত করা হয়। এটি তাদের দ্রুত চালাতে সহায়তা করবে না, তবে এটি আপনাকে দ্রুত লিখতে সহায়তা করবে।


খুব কম লোকই স্পষ্টভাবে ব্যবহার করছে local, তবে আমি মনে করি বেশিরভাগ লোকেরা স্ক্রিপ্টগুলি লিখে ফাংশনগুলিতে বিভক্ত হয়ে এখনও নকশার নীতি অনুসরণ করে। ইউইনাইন localকেবল বাগগুলি প্রবর্তন করা আরও শক্ত করে তোলে।
ভু

localভেরিয়েবলগুলি ফাংশন এবং তার শিশুদের জন্য উপলব্ধ করে তোলে, সুতরাং এটি একটি ভেরিয়েবলটি খুব ভাল লাগবে যা ফাংশন এ থেকে পাস করা যায় তবে বি ফাংশনটি উপলভ্য নয়, যা একই নামের সাথে ভিন্ন উদ্দেশ্য সহ ভেরিয়েবল রাখতে চায়। সুতরাং সুযোগটি সংজ্ঞায়িত করার পক্ষে এটি খুব ভাল, এবং ভু যেমন বলেছিলেন - কম বাগগুলি
সের্গি কলডিয়াজহনি

10

ইতিমধ্যে অন্যান্য উত্তরে দেওয়া থেকে সম্পূর্ণ ভিন্ন কারণ: এই কৌশলটি কখনও কখনও ব্যবহৃত হয়, যেখানে শীর্ষ স্তরের একক অ-কার্য-সংজ্ঞা বিবৃতিতে কল করা হয় main, স্ক্রিপ্টটি দুর্ঘটনাক্রমে কোনও খারাপ কাজ না করে তা নিশ্চিত করা is যদি স্ক্রিপ্টটি কেটে ফেলা হয়। প্রসেস A থেকে বি (শেল) প্রসেস করার জন্য স্ক্রিপ্টটি ছিন্ন করা যেতে পারে এবং পুরো স্ক্রিপ্টটি লেখার কাজ শেষ হওয়ার আগে কোনও কারণেই এটিকে বন্ধ করে দেয় process প্রক্রিয়াটি যদি কোনও দূরবর্তী উত্স থেকে স্ক্রিপ্টটি নিয়ে আসে তবে এটি সম্ভবত ঘটতে পারে। সুরক্ষা কারণে যে এটি একটি ভাল ধারণা নয়, এটি এমন কিছু যা করা হয়েছে এবং সমস্যাটি অনুমান করার জন্য কিছু স্ক্রিপ্ট পরিবর্তন করা হয়েছে।


5
মজাদার! তবে আমি মনে করি এটি উদ্বেগজনক যে প্রতিটি প্রোগ্রামে প্রত্যেককে সেই জিনিসগুলির যত্ন নিতে হবে। অন্যদিকে, main()পাইথনের ঠিক ঠিক এই প্যাটার্নটি যেখানে if __name__ == '__main__': main()ফাইলের শেষে কেউ ব্যবহার করে।
মার্টিন উয়েডিং

1
পাইথন আইডিয়ামটিতে অন্যান্য স্ক্রিপ্টগুলি importচলমান স্ক্রিপ্টটি চালিয়ে না দেওয়ার সুবিধা রয়েছে main। আমি মনে করি অনুরূপ প্রহরীকে ব্যাশ স্ক্রিপ্টে রাখা যেতে পারে।
জেক কোব

@ জেক কোব হ্যাঁ আমি এখন এটি সমস্ত নতুন বাশ স্ক্রিপ্টগুলিতে করি। আমার কাছে একটি স্ক্রিপ্ট রয়েছে যা সমস্ত নতুন স্ক্রিপ্ট দ্বারা ব্যবহৃত ফাংশনগুলির মূল অবকাঠামো ধারণ করে। এই স্ক্রিপ্টটি উত্সাহিত বা কার্যকর করা যেতে পারে। যদি উত্সাহিত হয় তবে এর মূল কাজটি কার্যকর করা হয় না। উত্স বনাম নির্বাহের সনাক্তকরণটি সত্য যে BASH_SOURCE এ কার্যকরকারী স্ক্রিপ্টের নাম ধারণ করে। এটি যদি মূল স্ক্রিপ্টের মতো হয় তবে স্ক্রিপ্টটি কার্যকর করা হচ্ছে। অন্যথায়, এটি উত্সাহিত করা হচ্ছে।
ডকসালভেজার

7

একটি প্রক্রিয়া একটি ক্রম প্রয়োজন। বেশিরভাগ কাজ ক্রমানুসারে হয়। অর্ডারটি নিয়ে গোলমাল করার কোনও অর্থ নেই।

তবে প্রোগ্রামিং সম্পর্কে অতি বড় বিষয় - যা স্ক্রিপ্টিং অন্তর্ভুক্ত - পরীক্ষা করছে। পরীক্ষা, পরীক্ষা, পরীক্ষা করা হচ্ছে। আপনার স্ক্রিপ্টগুলির যথার্থতা যাচাই করতে বর্তমানে আপনার কাছে কোন পরীক্ষার স্ক্রিপ্ট রয়েছে?

আপনার বস আপনাকে স্ক্রিপ্টের বাচ্চা থেকে প্রোগ্রামার হওয়ার পথে পরিচালনার চেষ্টা করছেন। এটি প্রবেশের জন্য একটি ভাল দিক you আপনার পরে আসা লোকেরা আপনাকে পছন্দ করবে।

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

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

পরে এখনও, আপনি উপলব্ধি করতে পারেন আপনি এখন নিজের লিখিত অনেকগুলি সহায়ক ফাংশনের লাইব্রেরি লিখেছেন যা আপনি আপনার অনেক স্ক্রিপ্টে ব্যবহার করেন।


6

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

আমি আপনাকে এর মতো নির্দেশনা দিয়েছি কিনা তা বিবেচনা করুন:

Place your hands on your desk.
Tense your arm muscles.
Extend your knee and hip joints.
Relax your arms.
Move your arms backwards.
Move your left leg backwards.
Move your right leg backwards.
(continue for 10,000 more lines)

আপনি অর্ধেক পেরিয়ে যাওয়ার সময় পর্যন্ত, বা এমনকি 5% এর মধ্য দিয়ে আপনি প্রথম বেশ কয়েকটি পদক্ষেপ কী তা ভুলে গেছেন। আপনি সম্ভবত বেশিরভাগ সমস্যাগুলিকে চিহ্নিত করতে পারেননি, কারণ আপনি গাছের জন্য বন দেখতে পাচ্ছেন না। ফাংশনগুলির সাথে তুলনা করুন:

stand_up();
walk_to(break_room);
pour(coffee);
walk_to(office);

এটি অবশ্যই অনেক বেশি বোধগম্য, আপনি লাইন বাই লাইন অনুক্রমিক সংস্করণে কত মন্তব্য লিখতে পারেন তা নির্বিশেষে। এছাড়া এটা তোলে পর্যন্ত সম্ভাবনা বেশি আপনি দেখতে পাবেন যে আপনি ভুলে গেছি করা কফি, এবং সম্ভবত () sit_down ভুলে শেষে। আপনার মন যখন গ্রেপ এবং অ্যাজক রেজিক্সগুলির বিশদটি নিয়ে ভাবছে, আপনি বড় ছবি ভাবতে পারবেন না - "যদি কফি তৈরি না হয় তবে কী হবে"?

কার্যাদি প্রাথমিকভাবে আপনাকে বড় ছবিটি দেখার অনুমতি দেয় এবং লক্ষ্য করুন যে আপনি কফি তৈরি করতে ভুলে গেছেন (বা কেউ চা পছন্দ করতে পারে)। অন্য সময়ে, মনের এক ভিন্ন ফ্রেমে আপনি বিস্তারিত বাস্তবায়ন সম্পর্কে উদ্বিগ্ন।

অন্যান্য উত্তরে অবশ্যই অন্যান্য বেনিফিট রয়েছে। অন্য উত্তরে পরিষ্কারভাবে বলা হয়নি এমন আরেকটি সুবিধা হ'ল ফাংশনগুলি এমন একটি গ্যারান্টি সরবরাহ করে যা বাগগুলি প্রতিরোধ ও স্থির করতে গুরুত্বপূর্ণ। যদি আপনি আবিষ্কার করেন যে সঠিক ফাংশন ওয়াক_ টো () এর কিছু ভেরিয়েবল was foo ভুল ছিল, তবে আপনি জানেন যে সেই সমস্যা দ্বারা প্রভাবিত হতে পারে এমন সমস্ত কিছুই, এবং যা কিছু হতে পারে তার সন্ধানের জন্য আপনাকে কেবল সেই ফাংশনের অন্যান্য 6 টি লাইন দেখতে হবে এটি ভুল হতে হয়েছে। (যথাযথ) ফাংশন ব্যতীত, পুরো সিস্টেমের কিছু এবং সমস্ত কিছু foo ভুল হওয়ার কারণ হতে পারে এবং যে কোনও কিছু এবং সমস্ত কিছুই $ foo দ্বারা প্রভাবিত হতে পারে। সুতরাং আপনি প্রোগ্রামের প্রতিটি লাইন পুনরায় পরীক্ষা না করে safely foo নিরাপদে ঠিক করতে পারবেন না। যদি function foo কোনও ফাংশনে স্থানীয় হয়,


1
এটি bashসিনট্যাক্স নয় । যদিও এটি লজ্জাজনক; আমি মনে করি না এর মতো ফাংশনে ইনপুট দেওয়ার কোনও উপায় আছে। (যেমন pour();< coffee)। এটি দেখতে আরও বেশি লাগে c++বা php(আমার মনে হয়)।
ভয়েস

2
@ tjt263 প্রথম বন্ধনী ছাড়াই, এটি বাশ বাক্য গঠন: কফি .ালা। পেরেনগুলির সাথে, এটি অন্য যে কোনও ভাষাতেই বেশ। :)
রে মরিস

5

প্রোগ্রামিং সম্পর্কে কিছু প্রাসঙ্গিক কৌশল:

  • আপনার বস যদি তা না করে তবে আপনার প্রোগ্রামটি পরিবর্তিত হবে
  • কেবল কোড এবং ইনপুট প্রোগ্রামের আচরণকে প্রভাবিত করে।
  • নামকরণ কঠিন।

মন্তব্যগুলি * আপনার ধারণাগুলি কোড * তে পরিষ্কারভাবে প্রকাশ করতে না পারা এবং পরিবর্তনের সাথে আরও খারাপ (বা কেবল ভুল) হয়ে উঠার জন্য স্টপ-গ্যাপ হিসাবে শুরু হয়। অতএব, যদি সম্ভব হয় তবে কোড হিসাবে কোড বোঝার জন্য ধারণা, কাঠামো, যুক্তি, শব্দার্থক শব্দ, প্রবাহ, ত্রুটি পরিচালনা এবং অন্য যে কোনও কিছু প্রকাশ করুন

এটি বলেছিল যে, বাশ ফাংশনগুলির বেশিরভাগ ভাষায় কিছু সমস্যা পাওয়া যায় নি:

  • বাশে নেমস্পেসিং ভয়ঙ্কর। উদাহরণস্বরূপ, localকীওয়ার্ডের ফলাফলটি ভুলে যাওয়া বিশ্বব্যাপী নেমস্পেসকে দূষিত করে।
  • এর প্রস্থান কোডটি হারাতেlocal foo="$(bar)" ফলাফল ব্যবহার করা ।bar
  • কোনও নামকরণকৃত প্যারামিটার নেই, তাই আপনাকে "$@"বিভিন্ন প্রসঙ্গের অর্থ কী তা মনে রাখতে হবে ।

* যদি এটি ক্ষুব্ধ হয় তবে আমি দুঃখিত, তবে কয়েক বছর ধরে মন্তব্য ব্যবহার করার পরে এবং সেগুলি ছাড়াই বিকাশের পরে ** আরও কয়েক বছর ধরে এটি পরিষ্কার যেটি সর্বোত্তম।

** লাইসেন্সিং, এপিআই ডকুমেন্টেশন এবং এর মতো মন্তব্যগুলি ব্যবহার করা এখনও প্রয়োজনীয়।


আমি তাদের ঘোষণা ফাংশন শুরুতে নাল ... প্রায় সব স্থানীয় ভেরিয়েবল সেট local foo=""তারপর ফলাফলের কাজ করার জন্য কমান্ড সঞ্চালনের ব্যবহার করে সেগুলি স্থাপন ... foo="$(bar)" || { echo "bar() failed"; return 1; }। এটি যখন আমাদের প্রয়োজনীয় মান সেট করা যায় না তখন তা আমাদের দ্রুত কার্যকারিতা থেকে সরিয়ে দেয়। কোঁকড়া ধনুর্বন্ধনী ব্রেসগুলি return 1কেবলমাত্র ব্যর্থতার উপর কার্যকর করা হয় তা নিশ্চিত করার জন্য প্রয়োজনীয় ।
ডকসালভেজার

5

সময়ই টাকা

আছে অন্য ভালো উত্তর যে প্রযুক্তিগত কারণের উপর হালকা ছড়িয়ে লিখতে modularly একটি স্ক্রিপ্ট, সম্ভাব্য দীর্ঘ, কাজ পরিবেশে বিকশিত দ্বারা ব্যবহার করা যেতে বিকশিত ব্যক্তি একটি গ্রুপ এবং আপনার নিজস্ব ব্যবহারের জন্য শুধুমাত্র।

আমি একজনের প্রত্যাশার দিকে মনোনিবেশ করতে চাই: একটি কাজের পরিবেশে "সময় সময়" । তাই বাগ এবং আপনার কোড পারফরমেন্স অভাবে একসাথে মূল্যায়ন করা হয় readibility , testability, maintainability, refactorability, পুনর্ব্যাবহার্যোগ্যতা ...

লিখন "মডিউল" একটি কোড দ্বারা শুধুমাত্র প্রয়োজন পড়ার সময় লাঘব হবে সংকেতপদ্ধতিরচয়িতা নিজেই, কিন্তু এমনকি পরীক্ষকের দ্বারা বা মনিব দ্বারা ব্যবহৃত সময়। তদ্ব্যতীত নোট করুন যে একজন বসের সময় সাধারণত কোডারের সময় বেশি দেওয়া হয় এবং আপনার বস আপনার কাজের মানের মূল্যায়ন করবে।

উপরন্তু লেখা স্বাধীন "মডিউল" একটি কোড (এমনকি একটি ব্যাশ স্ক্রিপ্ট) আপনি কাজ করার অনুমতি দেবে "সমান্তরাল" আপনার দলের সামগ্রিক উৎপাদন সময় সংক্ষেপিত এবং সেরা একক এর দক্ষতার ব্যবহার করে, পর্যালোচনা বা সঙ্গে একটি অংশ পুনর্লিখন অন্যান্য উপাদান সহ অন্যের উপর কোনও পার্শ্ব প্রতিক্রিয়া নেই, আপনি যে কোডটি লিখেছেন তা পুনরায় ব্যবহার করতে "যেমন আছে"অন্য প্রোগ্রাম / স্ক্রিপ্টের জন্য, লাইব্রেরি (বা স্নিপেটের লাইব্রেরি) তৈরি করা, সামগ্রিক আকার এবং ত্রুটির সম্পর্কিত সম্ভাবনা হ্রাস করার জন্য, প্রতিটি একক অংশটি ডিবাগ করে পরীক্ষা করা ... এবং অবশ্যই এটি যৌক্তিক বিভাগে আপনার প্রোগ্রামটিকে সংগঠিত করবে / স্ক্রিপ্ট এবং এর পাঠযোগ্যতা বৃদ্ধি। সমস্ত জিনিস যা সময় এবং তাই অর্থ সাশ্রয় করবে। অসুবিধাটি হ'ল আপনাকে মানকে আটকে থাকতে হবে এবং আপনার ফাংশনগুলিতে মন্তব্য করতে হবে (যে কোনও কাজের পরিবেশে আপনাকে যা করতে হবে)।

একটি মান মেনে চলা আপনার শুরুর দিকে আপনার কাজকে কমিয়ে দেবে তবে এটি পরে অন্য সমস্ত (এবং আপনারও) কাজ দ্রুত করবে। প্রকৃতপক্ষে যখন সহযোগিতা জড়িত সংখ্যক লোকের সংখ্যা বৃদ্ধি পায় এটি একটি অনিবার্য প্রয়োজন হয়ে ওঠে। সুতরাং, উদাহরণস্বরূপ, এমনকি যদি আমি বিশ্বাস করি যে গ্লোবাল ভেরিয়েবলগুলি বিশ্বব্যাপী সংজ্ঞায়িত করতে হবে এবং কোনও ফাংশনে নয়, তবে আমি এমন একটি মান বুঝতে পারি যা তাদের declare_variables()প্রথম লাইনে সর্বদা নামক একটি ফাংশনগুলিতে ইনজিআইলাইজ করে main()...

সর্বশেষে তবে সর্বনিম্ন নয়, আধুনিক উত্স কোড সম্পাদকগুলিতে বা পৃথকভাবে পৃথক রুটিনগুলি ( কোড ফোল্ডিং ) দেখানোর বা আড়াল করার সম্ভাবনাটিকে হ্রাস করবেন না । এটি কোডটি কমপ্যাক্ট রাখবে এবং ব্যবহারকারীর পুনরায় সময় সাশ্রয়কে কেন্দ্র করে।

এখানে চিত্র বর্ণনা লিখুন

এখানে উপরে আপনি দেখতে পাবেন যে কীভাবে এটি কেবল ফাংশনটি প্রকাশ পেয়েছেwalk_into_bar() । এমনকি অন্যান্যগুলির মধ্যেও প্রতিটি লাইন 1000 লম্বা ছিল, আপনি এখনও একটি পৃষ্ঠাতে সমস্ত কোড নিয়ন্ত্রণে রাখতে পারেন। নোট করুন এটি এমনকি সেই বিভাগটি ভাঁজ করা হয়েছে যেখানে আপনি ভেরিয়েবলগুলি ঘোষণা / আরম্ভ করতে যান।


1

অন্যান্য উত্তরে প্রদত্ত কারণগুলি বাদে:

  1. মনোবিজ্ঞান: এমন প্রোগ্রামার যার প্রডাক্টিভিটি কোডের লাইনে পরিমাপ করা হচ্ছে অকারণে ভার্বোজ কোড লেখার জন্য উত্সাহী হবে। যত বেশি কোড কোডের লাইনে ফোকাস করছে, প্রোগ্রামারকে তত বেশি উদ্দীপকটি তার কোডটি বিনা শর্তে জটিলতার সাথে প্রসারিত করতে হবে। এটি অনাকাঙ্ক্ষিত যেহেতু বর্ধিত জটিলতা রক্ষণাবেক্ষণের ব্যয় বৃদ্ধি করতে এবং বাগ ফিক্সিংয়ের জন্য প্রয়োজনীয় প্রচেষ্টা বাড়িয়ে তুলতে পারে।

এটি এত খারাপ উত্তর নয়, যেমন ডাউনভোটরা বলে। দ্রষ্টব্য: agc বলছে, এটিও একটি সম্ভাবনা, এবং হ্যাঁ, এটিও। তিনি বলেন না যে এটিই একমাত্র সম্ভাবনা, এবং কাউকেই দোষারোপ করে না, কেবল ঘটনাগুলিকেই বর্ণনা করে। যদিও আমি মনে করি আজ প্রত্যক্ষভাবে প্রত্যক্ষহীন প্রত্যক্ষ "কোড লাইন" -> "contract" শৈলীর চুক্তি কাজ, পরোক্ষভাবে এটি বেশ সাধারণ, হ্যাঁ, নেতৃবৃন্দ / কর্তাদের দ্বারা উত্পাদিত কোডের গণনা গণনা করা হয়।
ব্যবহারকারী 259412

0

প্রায়শই অবহেলিত হওয়ার আরেকটি কারণ হ'ল বাশের সিনট্যাক্স পার্সিং:

set -eu

echo "this shouldn't run"
{
echo "this shouldn't run either"

এই স্ক্রিপ্টটিতে স্পষ্টতই একটি সিনট্যাক্স ত্রুটি রয়েছে এবং বাশ এটিকে চালানো উচিত নয়, তাই না? ভুল।

~ $ bash t1.sh
this shouldn't run
t1.sh: line 7: syntax error: unexpected end of file

আমরা যদি কোনও ফাংশনে কোডটি গুটিয়ে রাখি তবে এটি ঘটবে না:

set -eu

main() {
  echo "this shouldn't run"
  {
  echo "this shouldn't run either"
}

main
~ $ bash t1.sh
t1.sh: line 10: syntax error: unexpected end of file
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.