برای چاپ مقدار متغیر در شل، قالب printf را ثابت نگه دارید و داده را در آرگومان جدا و داخل کوتیشن دوتایی بدهید؛ مانند printf ‘%s\n’ “$value”. این روش متن دارای فاصله، درصد و بکاسلش را از دستور قالببندی جدا میکند. در این آموزش تفاوت قالب و داده، newline و چند خطای رایج echo را با مثالهای بدون تغییر فایل بررسی میکنیم.
۱. قالب و داده دو آرگومان متفاوتاند
value='alpha beta %s'
printf '%s\n' "$value"
در قالب، %s میگوید آرگومان بعدی بهصورت متن چاپ شود و \n در قالب پایان خط میسازد. خروجی دقیق نمونه، alpha beta %s است؛ درصد داخل مقدار متغیر دوباره بهعنوان دستور قالب تفسیر نمیشود. کوتیشن دوتایی دور “$value” نیز از شکستن مقدار بر اساس فاصله و تفسیر الگوی نام فایل توسط شل جلوگیری میکند.
راهنمای GNU printf قرارداد format و آرگومانها را شرح میدهد و تفاوت احتمالی نسخهٔ داخلی شل با ابزار بیرونی را گوشزد میکند. مثالهای این متن با printf داخلی Bash5.۲.۳۷ بررسی شدهاند؛ روی همهٔ افزونهها و پیادهسازیهای printf ادعای یکسان نداریم. راهنمای کوتیشن دوتایی Bash نیز رفتار گسترش متغیر در کوتیشن را توضیح میدهد.
۲. مقدار متغیر را جای قالب نگذارید
| روش | معنی |
|---|---|
printf با قالب ثابت %s |
داده در آرگومان جدا چاپ میشود |
قرار دادن value در جای format |
درصدها و escapeهای داده ممکن است دستور قالب شوند |
| متغیر بدون کوتیشن | ممکن است به چند آرگومان یا نام فایل گسترش پیدا کند |
در نمونهٔ صحیح بالا، هر متن ورودی یک مقدار است. اگر خود متغیر را format کنید، محتوای آن میتواند معنای قالببندی پیدا کند و خروجی قابل پیشبینی نباشد. برای چاپ دادهٔ ناشناخته، الگوی قالب ثابت را حفظ کنید؛ این قاعده جای اعتبارسنجی داده برای کاربردهای دیگر را نمیگیرد.
۳. چاپ درصد و پایان خط
printf 'progress=%s%%\n' '75'
خروجی progress=۷۵% است. دو علامت %% در قالب، یک درصد معمولی چاپ میکند؛ %s جای مقدار75 است. اگر قالب \n نداشته باشد، printf خودکار پایان خط اضافه نمیکند. این موضوع در فایلهای متنی، نمایش prompt و شمارش خط اهمیت دارد.
printf '[%s]\n' alpha beta
در Bash این قالب برای آرگومانهای باقیمانده تکرار میشود و دو خط [alpha] و [beta] ساخته میشود. اگر میخواستید فقط یک متن با فاصله چاپ شود، باید آن را یک آرگومان میدادید:
printf '[%s]\n' 'alpha beta'
۴. بکاسلش داخل مقدار با قالب فرق دارد
value='line1\nline2'
printf '%s\n' "$value"
خروجی، یک خط دارای متن تحتاللفظی line1\nline2 است. %s محتوای آن آرگومان را مانند قالب دوباره تفسیر نمیکند. این ویژگی برای نمایش متن خام مفید است. گزینهها یا formatهای تفسیرکنندهٔ escape مانند %b کار دیگری دارند؛ آنها را بدون نیاز به دادهٔ ناشناخته اعمال نکنید.
نکته: «چاپ مطمئن» در اینجا یعنی جداکردن داده از format و کنترل quoting. دادهٔ دارای کاراکتر کنترل ترمینال یا رمز محرمانه همچنان به بررسی جداگانه نیاز دارد؛ هیچ راز واقعی را برای آزمایش چاپ نکنید.
۵. چه زمانی echo کافی نیست؟
برای پیام ثابت و ساده، echo معمولاً راحت است. اما تفسیر -n، بکاسلشها و گزینهها بین محیطها متفاوت است؛ مستند رسمی GNU echo برای دادهٔ متغیر و رفتار قابل پیشبینی به printf اشاره میکند. بهجای آزمون اتفاقی در یک شل، قالب و پایان خط را صریح بنویسید.
| نیاز | الگوی روشن |
|---|---|
چاپ یک مقدار و newline |
printf با %s و \n در format |
| چاپ متن درصددار | داده در %s یا %% در قالب ثابت |
چاپ بدون newline |
قالب %s بدون \n |
| نمایش متن خامِ دارای بکاسلش | %s؛ نه تفسیر دوبارهٔ escape |
از این موضوع نتیجه نگیرید همهٔ اسکریپتهای قدیمی باید یکجا عوض شوند. هنگام اصلاح، خروجی دقیق، تعداد آرگومانها و وابستگی مرحلهٔ بعد را بررسی کنید.
۶. چکلیست خروجی قابل اتکا
- قالب ثابت است و از ورودی کاربر ساخته نمیشود.
- هر مقدار متغیر در آرگومان جدا و کوتیشن دوتایی قرار دارد.
- وجود یا نبود newline عمدی است.
- متن نمونه شامل فاصله، درصد و بکاسلش آزمایش شده است.
- دادهٔ خصوصی و کاراکترهای کنترل ناخواسته چاپ نمیشوند.
printf فایل را تغییر میدهد؟
در مثالهای بالا خیر؛ فقط روی stdout مینویسد. افزودن redirect میتواند فایل ایجاد یا بازنویسی کند و خارج از تمرین این مقاله است.
چرا خروجی چند خط شد؟
ابتدا ببینید چند آرگومان به printf رسیده و newline در قالب یا داده کجاست. قالب ممکن است برای آرگومانهای بیشتر تکرار شود؛ متغیر بدون کوتیشن نیز میتواند آرگومانها را بیشتر کند.
اگر خروجی printf را به فرمان بعدی میفرستید، تفاوت stdout و stderr و مفهوم Pipe در لینوکس را هم بررسی کنید تا پیام خطا را با دادهٔ خروجی اشتباه نگیرید.
۷. مسیر مطالعهٔ مرتبط
۸. منابع و دامنهٔ بررسی
منابع رسمی در ۳ نوامبر ۲۰۲۶ بررسی شدند. نمونهها در Bash ۵.۲.۳۷ و GNU Coreutils ۸.۳۲ در محیط MSYS روی ویندوز اجرا شدند؛ این آزمون، اجرای بومی روی یک توزیع لینوکس نیست. مستند آنلاین GNU میتواند نسخهٔ جدیدتری را شرح دهد؛ فقط گزینههای ذکرشده و بررسیشده مبنای مثالاند.