سؤال

بقدر ما أعرف أن هناك طريقتان لإنشاء متغيرات محلية في وظيفة bash: إنشاء subshell أو إعلان كل متغير كمحلية.

فمثلا:

# using local
function foo
{
  local count
  for count in $(seq 10)
  do
    echo $count
  done
}

أو

# using subshell
function foo
{
  (
    for count in $(seq 10)
    do
      echo $count
    done
  )
}

من الممكن أن يكون الإصدار باستخدام subshell أبسط في الكتابة لأنك لا تضطر إلى الاهتمام بإعلان جميع المتغيرات المحلية (ناهيك عن البيئة) التي تم إنشاؤها/تصديرها بواسطة أدوات مثل getopts). لكنني يمكن أن أتخيل أن إنشاء فرعي له النفقات العامة.

إذن ما هو النهج الأفضل؟ ما هي إيجابيات/سلبيات؟

هل كانت مفيدة؟

المحلول

ينطوي إنشاء قشرة فرعية fork(), ، لذلك بالتأكيد لديها النفقات العامة مقارنة مع متغير محلي. على الرغم من أن القواعد الفرعية رخيصة-فأنت لا تقلق بشأن تكلفتها عندما تحتاج إلى واحدة-فهي ليست حرة.

إذا كان البرنامج النصي الخاص بك يستخدم بشكل كبير والأداء مهم حقًا (لذلك سيكون لديك المئات من المستخدمين جميعهم يقومون بتشغيله في نفس الوقت ، عدة مرات في اليوم) ، فقد تقلق بشأن تكلفة أداء القشرة الفرعية. OTOH ، إذا قمت بتشغيله مرة واحدة في الشهر والبرنامج النصي ككل يعمل لمدة تقل عن 10 ثوانٍ ، فربما لن تفعل ذلك.

ومع ذلك ، فيما يتعلق بالوضوح ، من الأفضل أن تكون صريحًا وإعلان المتغيرات-فهو يقلل من خطر كسر النص لأن شخصًا ما يأتي ويقول "من الواضح أن هذا القشرة الفرعية غير مطلوبة" (وهو في الحقيقة ليس " T ؛ أرغب في إزالة القطع الفرعية من وظائفك).

انظر إلى تطور البرامج النصية بيرل. لقد بدأوا كجزء حرة للجميع مع وجود متغيرات إلى الوجود عند الطلب. لقد أصبحوا تدريجياً أكثر صرامة ، مع وجود أسلوب عادي الآن لتسجيل جميع المتغيرات. إلى حد ما ، اتبعت القذائف مسارًا مشابهًا - ولكن ليس بدقة مثل Perl. AWK هي أيضا دراسة حالة مثيرة للاهتمام. تستخدم وظائفها المتغيرات العالمية ما لم تكن وسيطات إلى الوظيفة ، مما يؤدي إلى كتابة وظائف مع 3 وسيطات نشطة (على سبيل المثال) و 5 وسيطات غير نشطة تحدد بشكل فعال المتغيرات المحلية. إنه غريب الأطوار قليلاً ، على الرغم من أنه "يعمل".

نصائح أخرى

الآن ، التأكد من أن جميع الوظائف تعلن دائمًا أن جميع المتغيرات محلية ، أمر صعب للغاية.

أعتقد أن هذا معرض للخطأ ويفضل دائمًا استخدام الوظائف الفرعية:

f() (
 echo "we are a subshell"
)

لا حاجة لإعلان المتغيرات المحلية - ولكن أيضًا لا توجد طريقة لتغيير المتغيرات العالمية. وهو أمر جيد في رأيي!

إحدى النتائج الإضافية هي أنك تحتاج دائمًا إلى التحقق من رمز الإرجاع / الخروج لهذه الوظائف والتصرف وفقًا لذلك! هذا ، لأنه لا يمكنك الخروج من البرنامج النصي من داخل وظيفة Subshell!

f() (
   echo "Trying to exit"
   exit 1
)

f
echo "Did not exit"

هذا لن يخرج من البرنامج النصي الخاص بك. تحتاج إلى القيام بذلك بهذه الطريقة:

f() (
   echo "Trying to exit"
   exit 1
)

f || exit $?
echo "Did not exit"

هذا سوف يخرج

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top