آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

پرسش و پاسخ شماره ۳۷

پرسش و پاسخ شماره ۳۷

چطور می‌توانم متن را با رنگهای مختلف چاپ کنم؟

در برنامه خود از رشته‌های escape رنگ ANSI استفاده نکنید! فرمان tput محاوره با بانک اطلاعاتی ترمینال به روشی معقول، را برای شما میسر می‌سازد:

  # Bourne
  tput setaf 1; echo this is red
  tput setaf 2; echo this is green
  tput bold; echo "boldface (and still green)"
  tput sgr0; echo back to normal

کاربران Cygwin: شما برای به دست آوردن tput نیاز به نصب بسته ncurses دارید( Where did "tput" go in 1.7? را ببینید).

tput بانک اطلاعاتی terminfo را می‌خواند که شامل تمام کُدهای escape لازم برای محاوره با ترمینال شما می‌باشد. این کدها در متغیر ‎$TERM‎ تعیین شده‌اند. برای اطلاعات تفصیلی صفحه‎ man terminfo(5)‎ را بخوانید.

دستور ‎tput sgr0‎ رنگها را دوباره به مقادیر پیش فرض تنظیم می‌کند. این دستور همچنین حالت حروف ضخیم ‎(tput bold)‎‏، underline، و غیره را غیر فعال می‌کند.

اگر رنگهای تفننی برای اعلان فرمان خود می‌خواهید، استفاده از مورد قابل مدیریت را در نظر بگیرید:

  # Bash
  red=$(tput setaf 1)
  green=$(tput setaf 2)
  blue=$(tput setaf 4)
  reset=$(tput sgr0)
  PS1='\[$red\]\u\[$reset\]@\[$green\]\h\[$reset\]:\[$blue\]\w\[$reset\]\$ '

توجه نمایید که ما از رشته‌های escape رنگ ANSI استفاده نکردیم. به جای آن ذخیره خروجی فرمان tput در متغیرها را به کار بردیم، که بعداً هنگامی که ‎ $PS1‎ بسط داده می‌شود، به کار می‌روند. ذخیره کمیت‌ها به معنای آنست که در هر نوبت نمایش اعلان، چندین انشعاب پردازش tput نداریم، tput فقط چهار بار در حین شروع اولیه پوسته فراخوانی می‌شود. علائم‎ \[‎ و ‎\]‎ اجازه می‌دهند bash بفهمد کدام قسمت‌های اعلان موجب حرکت نشانگر نشوند، بدون آنها سطرها به طور نادرست شکسته خواهند شد.

همچنین برای یک مرور اجمالی http://wiki.bash-hackers.org/scripting/terminalcodes ببینید.

در ادامه دامنه وسیع‌تری از رشته متغیرهای ترمینال آمده است. هر کدام را که می‌خواهید برگزینید:

# .متغیرها برای درخواستهای ترمینال
[[ -t 2 ]] && { 
    alt=$(      tput smcup  || tput ti      ) # Start alt display
    ealt=$(     tput rmcup  || tput te      ) # End   alt display
    hide=$(     tput civis  || tput vi      ) # Hide cursor
    show=$(     tput cnorm  || tput ve      ) # Show cursor
    save=$(     tput sc                     ) # Save cursor
    load=$(     tput rc                     ) # Load cursor
    bold=$(     tput bold   || tput md      ) # Start bold
    stout=$(    tput smso   || tput so      ) # Start stand-out
    estout=$(   tput rmso   || tput se      ) # End stand-out
    under=$(    tput smul   || tput us      ) # Start underline
    eunder=$(   tput rmul   || tput ue      ) # End   underline
    reset=$(    tput sgr0   || tput me      ) # Reset cursor
    blink=$(    tput blink  || tput mb      ) # Start blinking
    italic=$(   tput sitm   || tput ZH      ) # Start italic
    eitalic=$(  tput ritm   || tput ZR      ) # End   italic
[[ $TERM != *-m ]] && { 
    red=$(      tput setaf 1|| tput AF 1    )
    green=$(    tput setaf 2|| tput AF 2    )
    yellow=$(   tput setaf 3|| tput AF 3    )
    blue=$(     tput setaf 4|| tput AF 4    )
    magenta=$(  tput setaf 5|| tput AF 5    )
    cyan=$(     tput setaf 6|| tput AF 6    )
}
    white=$(    tput setaf 7|| tput AF 7    )
    default=$(  tput op                     )

    eed=$(      tput ed     || tput cd      )   # Erase to end of display
    eel=$(      tput el     || tput ce      )   # Erase to end of line
    ebl=$(      tput el1    || tput cb      )   # Erase to beginning of line
    ewl=$eel$ebl                                # Erase whole line
    draw=$(     tput -S <<< '   enacs
                                smacs
                                acsc
                                rmacs' || { \
                tput eA; tput as;
                tput ac; tput ae;         } )   # Drawing characters
    back=$'\b'
} 2>/dev/null ||:

در بالا موقعی که stderr به ترمینال متصل نباشد، متغیرهای تنظیم نشده رها می‌شوند و متغیر های رنگ تنظیم نشده برای ترمینالهای تک رنگ چشم‌پوشی می‌شوند. اجراهای جایگزین tput به کد اجازه می‌دهند روی سیستم‌هایی که در آنها tput به جای نامهای ANSI مربوطه، نام‌های قدیمی termcap را می‌پذیرد، کار را ادامه دهد. این کد همچنین از ‎2>/dev/null ||:‎ برای خاموش کردن خطاهای بالقوه و پرهیز از عدم پیشروی اسکریپت در اثر خطا، استفاده می‌کند. این مورد اجازه می‌دهد این کد در گستره‌ای از وضعیت‌ها از قبیل آن اسکریپت‌ها که ‎set -e‎ را به کار می‌برند و ترمینال‌ها یا سیستم عامل‌هایی که از رشته‌های معینی پشتیبانی می‌کنند، قابل استفاده باشد(کد از http://to.lhunath.com/bashlib اقتباس گردیده است).

مباحثه

این مطلب بحث‌انگیز خواهد بود، اما من موافقت نمی‌کنم و پیشنهاد می‌کنم از کدهای escape در ANSI به صورت hard-codedزیرنویس1 استفاده کنید به دلیل آنکه در دنیای واقعی بانک‌های اطلاعاتی مربوط به ترمینال‌ها بیشتر اوقات ناقص می‌باشند.

tput setaf‎ به طور لفظی به معنای «قرار دادن ANSI در پیش زمینه» است و نباید هیچ تفاوتی با رشته escapeهای ANSI به صورت hard-coded داشته باشد، غیر ازآنکه با بانکهای اطلاعاتی ناقص terminfo کار خواهد کرد، بنابراین رنگها در یک VT با نوع ترمینال ‎linux-16color‎ یا هر نوع ترمینال به شرطی که واقعاً ترمینالی با توانایی نمایش شانزده رنگ ANSI باشد، به طور صحیح دیده خواهند شد.

بنابراین تنظیم آن متغیرها به رشته‌های ANSI به صورت hard-coded را در نظر بگیرید.همچون:

  # Bash
  white=$'\e[0;37m'
  • شما فرض می‌کنید تمام ترمینالهای جهان که شما در هر صورت استفاده خواهید نمود همواره با یک مجموعه منفرد رشته‌های escape مطابقت می‌کنند. این یک فرض بسیار ضعیف است. شاید پیری خود را نمایش می‌دهم، اما در اولین شغل خود بعد از دانشگاه، در سال ‎1993-1994‎، با طیف متنوع گسترده‌ای از ترمینالهای فیزیکی کار کردم ‎(IBM 3151, Wyse 30, NCR or other, etc.)‎ همه در همان محل کار. تمام آنها طرح کلیدهای متفاوت، رشته‌های escape متفاوت داشتند. اگر من رشته‌های escape یک ترمینال را به طوری که شما پیشنهاد می‌کنید به صورت hard-code استفاده می‌کردم، فقط در یکی از آن ترمینالها کار می‌کرد، و سپس اگر من از اداره دیگری یا از کنسول سرویس‌دهنده لاگین می‌کردم، سردرگم می‌شدم. بنابراین، اگر برای استفاده شخصی، این کار شما را خوشحال می‌کند، من نمی‌توانم جلوی شما را بگیرم. اما اندیشه نوشتن اسکریپتی که از رشته‌های escape به طور hard-coded استفاده کند و سپس توزیع آن برای دیگران باید به فوریت دور انداخته شود. - GreyCat

    • من گفتم این بحث‌انگیز خواهد شد، اما دیدگاه جایگزینی وجود دارد. امروزه بسیاری افراد در هر طرف از لینوکس در سرویس‌دهنده‌های خود یا میزکارهایشان با پروفایلهای خود، استفاده می‌کنند. بانک اطلاعاتی ترمینال برای لینوکس ۱۶ رنگ نابسامان است. با انجام این کار به آن روش «درست»(مترجم: توجه دارید که نویسنده کلمه درست را با کنایه استفاده نموده است)، آنها متوجه خواهند شد که رنگهایشان در ترمینال مجازی یکی از ttyهای کنسول به طور صحیح کار نمی‌کند. با اجرای آن روش «نادرست»، اگر از xterm واقعی یامشتق نزدیک به آن استفاده کنند، فقط رنگ قرمز روشن پررنگ می‌شود. اگر بانک اطلاعاتی ترمینال، در مورد رایجی مانند لینوکس ۱۶ رنگ نمی‌تواند صحیح باشد، پیشنهاد تکیه‌کردن به آن مشکل است. اشخاص باید آگاه باشند که آن روش به طور صحیح کار نمی‌کند، خودتان آن ۱۶ رنگ اول را در یک ترمینال مجازی لینوکس با linux-16color امتحان کنید. من می‌دانم که ANSI فقط نامها را تعیین نموده نه رنگمایه‌ها را، اما ‎به وضوح setaf 7‎ قرار نیست به دیدن متن سیاه منجر گردد، چون white نامیده شده است. من شرط می‌بندم که افراد بیشتری برای سرویس‌دهنده‌های خود از لینوکس استفاده می‌کنند تا دیگر سیستم‌های یونیکسی، و اگر از دیگر سیستم‌های مبتنی بر یونیکس یا یونیکس حقیقی استفاده می‌کنند، احتمالاً از ریزه‌کاری‌ها آگاه می‌باشند . یک تازه‌کار در لینوکس، بعد از پیروی از «روش درست» و دریافتن آنکه رنگهایش در ترمینال مجازی به طور صحیح کار نمی‌کنند، بسیار شگفت‌زده می‌شود. البته کار درست اصلاح فایل terminfo است، اما آن کاری است که در توانایی من نیست، هرچند که من به طور خاص باگ مربوط به linux-16color راگزارش کرده‌ام، چه تعداد باگ دیگر در آن وجود دارد؟ تنها کار کاملاً صحیح، hard-code نمودن رشته‌ها برای تمام ترمینالهایی است که خودتان با آنها مواجه خواهید شد، که همان کاری است که قرار است terminfo انجام بدهد تا شما مجبور به انجام آن نشوید. به هرحال حداقل در این حالت(و حالت بسیار رایج) مشکل‌دار است، بنابراین اعتماد به آن برای انجام صحیح این کار نیز مورد تردید است. من در اینجا اضافه می‌کنم که احترام بسیاری برای Greycat قائل هستم، و او یک کارشناس خبره در بسیاری از حوزه‌های IT می‌باشد، من کاملاً قبول دارم که از چنان عمق دانشی مانند او برخوردار نیستم، اما آیا هرگز شما مشغول کار روی یک ‎Wyse 30‎ خواهید بود؟ برای اینکه کاملاً روشن شود، پیشنهاد می‌کنم که شما برای پروفایل و استفاده‌های شخصی خود، رنگهای hard-coded را در نظر بگیرید، اگر قصد نوشتن اسکریپت کاملاً قابل حملی برای استفاده دیگران در سیستم‌های بیرونی را دارید، آنوقت شما باید به ‎terminfo/termcap‎ تکیه کنید، حتی اگر دارای باگ باشند.

  • من قبلاً هرگز linux-16color نشنیده بودم. این یک مدخل terminfoنصب شده در دبیان نیست، یا حداقل به طور پیش فرض نیست. اگر فروشنده شما بانک اطلاعاتی terminfo خراب عرضه می‌کند، یک فهرست باگ گزارش کنید. ضمناً، سیستمی که مدخل مورد نیاز شما در آن خراب نیست را یافته، و آن مدخل را به سیستم خراب کپی کنید -- یا خودتان آنرا بنویسید. این کاری است که بقیه دنیا همیشه انجام می‌دهند. مدخل‌های terminfo ابتدا همین گونه به وجود آمده‌اند. کسی باید آنها را می‌نوشت.
  • console-colors.png

  • -- GreyCat


CategoryShell

پرسش و پاسخ 37 (آخرین ویرایش ‎2012-10-25 17:54:48‎ توسط Lhunath)


  1. مترجم: hard-coded به رفتاری گفته می‌شود که داده ‌ها به طور مستقیم داخل برنامه و احتمالاً در چندین محل نوشته می‌شوند به طوری که به آسانی نمی‌توانند اصلاح شوند. (1)


نظرات 0 + ارسال نظر
ایمیل شما بعد از ثبت نمایش داده نخواهد شد