فصل ‎37‎-‏ Bash، نگارش‌های ‎2‎‏، ‎3‎‏، و ‎4‎

فصل ‎37‎-‏ Bash، نگارش‌های ‎2‎‏، ‎3‎‏، و ‎4‎

فهرست مطالب
‎37.1‎-‏ Bash، نگارش ‎2‎
‎37.2‎-‏ Bash، نگارش ‎3‎
‎37.2.1‎-‏ Bash، نگارش ‎3.1‎
‎37.2.2‎-‏ Bash، نگارش ‎3.2‎
‎37.3‎-‏ Bash، نگارش ‎4‎
‎37.3.1‎-‏ Bash، نگارش ‎4.1‎
‎37.3.2‎-‏ Bash، نگارش ‎4.2‎


‎37.1‎- ‏Bash، نگارش ‎2‎

نگارش جاری Bash، آن نسخه‌ای که روی ماشین شما در حال اجراست، به احتمال بسیار نگارش ‎2.xx.yy‎‏، ‎3.xx.yy‎‏، یا ‎4.xx.yy‎ است.

bash$ echo $BASH_VERSION
3.2.25(1)-release

در به روزرسانی نگارش 2 زبان اسکریپت‌نویسی Bash کلاسیک، متغیرهای آرایه‌ای، بسط رشته و پارامتر، و یک شیوه مناسب‌تری از ارجاعات غیر مستقم متغیر در میان ویژگی‌های دیگر اضافه گردید.

مثال ‎37-1‎- بسط رشته

#!/bin/bash

# بسط رشته.
#                            معرفی شده در Bashنگارش ‎2‎

#             رشته‌هایی به شکل ‎$'xxx'‎ دارای کاراکترهای
#+                استاندارد escape شده تفسیر گردیدند. 

echo $'Ringing bell 3 times \a \a \a'
     # با برخی ترمینال‌ها ممکن است فقط یکبار زنگ بزند.
     #                                         یا ...
     #     بسته به تنظیمات ترمینال ممکن است زنگ نزند.
echo $'Three form feeds \f \f \f'
echo $'10 newlines \n\n\n\n\n\n\n\n\n\n'
echo $'\102\141\163\150'
     #   B   a   s   h
     #                         معادل اکتال کاراکترها.

exit

مثال ‎37-2‎- ارجاعات غیر مستقیم متغیر - روش جدید

#!/bin/bash

#                         ارجاع غیر مستقیم متغیر.
# این دارای مقداری از خصوصیات ارجاع‌ها در ‎C++‎ است.


a=letter_of_alphabet
letter_of_alphabet=z

echo "a = $a"                 #     ارجاع مستقیم.

echo "Now a = ${!a}"          # ارجاع غیر مستقیم.
#نشانه‌گذاری ‎${!variable}‎ قابل درک‌تر از نشانه‌گذاری
#+                   قدیمی ‎eval var1=\$$var2‎ است.

echo

t=table_cell_3
table_cell_3=24
echo "t = ${!t}"                      # t = 24
table_cell_3=387
echo "Value of t changed to ${!t}"    #    387
# eval لازم نیست.

#   این برای مراجعه به عناصر یک آرایه یا جدول، یا
#+      برای شبیه‌سازی یک آرایه چند بعدی مفید است.
# یک گزینه شاخص‌گذاری (متشابه با اشاره‌گرهای حسابی)‏
#+                          چقدر خوب می‌شد. افسوس.

exit 0

# مثال ‎ind-ref.sh‎ را نیز ببینید.

مثال ‎37-3‎. کاربرد ساده بانک اطلاعاتی، با استفاده از ارجاع متغیر غیر مستقیم

#!/bin/bash
# resistor-inventory.sh
# کاربرد ساده بانک داده / مراجعه به جدول.

# ============================================================== #
# داده‌ها

B1723_value=470                                   # Ohms
B1723_powerdissip=.25                             # Watts
B1723_colorcode="yellow-violet-brown"             # Color bands
B1723_loc=173                                     # Where they are
B1723_inventory=78                                # How many

B1724_value=1000
B1724_powerdissip=.25
B1724_colorcode="brown-black-red"
B1724_loc=24N
B1724_inventory=243

B1725_value=10000
B1725_powerdissip=.125
B1725_colorcode="brown-black-orange"
B1725_loc=24N
B1725_inventory=89

# ============================================================== #


echo

PS3='Enter catalog number: '

echo

select catalog_number in "B1723" "B1724" "B1725"
do
  Inv=${catalog_number}_inventory
  Val=${catalog_number}_value
  Pdissip=${catalog_number}_powerdissip
  Loc=${catalog_number}_loc
  Ccode=${catalog_number}_colorcode

  echo
  echo "Catalog number $catalog_number:"

  # اکنون، بازیابی کمیت‌ها، با استفاده از ارجاع غیر مستقیم.
  echo "There are ${!Inv} of  [${!Val} ohm / ${!Pdissip} watt]\
  resistors in stock."  #        ^             ^

  # از Bash نگارش ‎4.2‎، شما می‌توانید ‎"ohm"‎ را با
  #  ‎\u2126‎ تعویض کنید (با استفاده از ‎echo -e‎).
  # مترجم: فرمان ‎echo -e $'\u2126'‎ نماد Ω را نمایش می‌دهد

  echo "These are located in bin # ${!Loc}."
  echo "Their color code is \"${!Ccode}\"."

  break
done

echo; echo

#                              تمرین‌ها:
#                      ------------------------
#  ‎(1‎ این اسکریپت را برای خواندن داده‌هایش از یک فایل بازنویسی کنید.
# ‎(2‎ این اسکریپت را برای استفاده از آرایه‌ها به جای ارجاع غیر مستقیم
#+                                        متغیر بازنویسی نمایید.
#                       کدام روش روان‌تر و به طور مستقیم قابل درک است؟
#                                  کد نویسی برای کدام روش آسان‌تر است؟


#                              یادداشت‌ها:
#                      ------------------------
# اسکریپت‌های پوسته برای هر کاری غیر از ساده‌ترین کاربردهای بانک داده‌
#+        نامناسب هستند، و حتی آنوقت هم درگیر راه‌حل‌های موقت می‌شوند.
# بسیار بهتر است از زبانی با پشتیبانی ذاتی از ساختارهای داده، مانند
#+        ‎C++‎ یا جاوا (یا حتی پرل) برای کار با داده‌ها استفاده گردد.

exit 0

مثال ‎37-4‎. استفاده از آرایه‌ها و ترفندهای متفرقه دیگر برای توزیع تصادفی یک دست ورق بین ۴ نفر

#!/bin/bash
# cards.sh

# توزیع تصادفی یک دست ورق بین چهار نفر.

UNPICKED=0
PICKED=1

DUPE_CARD=99

LOWER_LIMIT=0
UPPER_LIMIT=51
CARDS_IN_SUIT=13
CARDS=52

declare -a Deck
declare -a Suits
declare -a Cards

# پیاده‌سازی آن با یک آرایه منفرد سه بعدی، آسان‌تر وقابل درک‌تر خواهد بود.
#        شاید یک نگارش آینده از Bash آرایه‌های چند بعدی را پشتیبانی کند.


initialize_Deck ()
{
i=$LOWER_LIMIT
until [ "$i" -gt $UPPER_LIMIT ]
do
  Deck[i]=$UNPICKED   #تنظیم همه کارتهای دسته ورق به عنوان انتخاب نشده.
  let "i += 1"
done
echo
}

initialize_Suits ()
{
Suits[0]=C #Clubs
Suits[1]=D #Diamonds
Suits[2]=H #Hearts
Suits[3]=S #Spades
}

initialize_Cards ()
{
Cards=(2 3 4 5 6 7 8 9 10 J Q K A)
# روشی از مقدار دهی یک آرایه.
}

pick_a_card ()
{
card_number=$RANDOM
let "card_number %= $CARDS" # منحصر کردن محدوده به ‎0 - 51‎، یعنی ‎52‎ کارت.
if [ "${Deck[card_number]}" -eq $UNPICKED ]
then
  Deck[card_number]=$PICKED
  return $card_number
else  
  return $DUPE_CARD
fi
}

parse_card ()
{
number=$1
let "suit_number = number / CARDS_IN_SUIT"
suit=${Suits[suit_number]}
echo -n "$suit-"
let "card_no = number % CARDS_IN_SUIT"
Card=${Cards[card_no]}
printf %-4s $Card
                #    چاپ کارت‌ها در ستون‌های مرتب.
}

seed_random ()  #  بذر تولید کننده اعداد تصادفی.
{               # اگر این کار را نکنید چه می‌شود؟
seed=`eval date +%s`
let "seed %= 32766"
RANDOM=$seed
} # سایر روش‌های بذر پاشی تولید کننده عدد تصادفی را بررسی کنید.

deal_cards ()
{
echo

cards_picked=0
while [ "$cards_picked" -le $UPPER_LIMIT ]
do
  pick_a_card
  t=$?

  if [ "$t" -ne $DUPE_CARD ]
  then
    parse_card $t

    u=$cards_picked+1
    # موقتا،برگرداندن شاخص‌گذاری به مبنای شروع از یک. چرا؟
    let "u %= $CARDS_IN_SUIT"
    if [ "$u" -eq 0 ]   #      تست شرطی ‎if/then‎ تو در تو.
    then
     echo
     echo
    fi        # هر دسته با یک سطر خالی کنار گذاشته می‌شود.

    let "cards_picked += 1"
  fi  
done  

echo

return 0
}


#                برنامه‌نویسی ساخت‌یافته:
# منطق کل برنامه در توابع پیمانه‌ای شده.

#===============
seed_random
initialize_Deck
initialize_Suits
initialize_Cards
deal_cards
#===============

exit



#                              تمرین‌ ‎1‎:
#       توضیحاتی برای مستند کردن تمام این اسکریپت اضافه کنید.

#                              تمرین ‎2‎:
# یک روال (تابع) اضافه کنید که خال‌های هر نفر جور شده چاپ شود.
# شما می‌توانید سایر نوآوری‌هایی را که دوست دارید اضافه نمایید.

#                              تمرین ‎3‎:
#  منطق اسکریپت را ساده‌سازی کرده و کارایی آن را افزایش بدهید.