اص

اصول در AWK

1 تمرین

درباره‌ی اصول

ما زبان را AWK و برنامه‌ی اجرایی‌ای را که برنامه‌های AWK را تفسیر می‌کند awk یا gawk می‌نامیم.

الگوها و کنش‌ها

یک برنامه‌ی AWK از جفت‌های الگو-کنش تشکیل شده است

pattern1 { action1 }
pattern2 { action2 }
...

یک الگو می‌تواند یک الگوی عبارت باقاعده باشد که با ورودی مطابقت داده می‌شود. همچنین می‌تواند هر عبارتی باشد که نتیجه‌اش یک مقدار «درست» یا «غلط» است.

یک کنش یک یا چند دستور AWK است. آکولادهای پیرامون آن الزامی‌اند.

اگر نتیجه‌ی الگو درست باشد، کنش متناظر آن ارزیابی می‌شود.

رکوردها و فیلدها

AWK ورودی را به‌صورت مجموعه‌ای از رکوردها تجزیه می‌کند. هر رکورد به صفر یا چند فیلد تقسیم می‌شود.

رفتار پیش‌فرض چنین است:

  • تقسیم ورودی به رکوردها با استفاده از خط جدید به‌عنوان «جداکننده‌ی رکورد»، به‌طوری که هر خط یک رکورد است.
  • تقسیم رکورد به فیلدها با استفاده از فضای خالی به‌عنوان «جداکننده‌ی فیلد»، به‌طوری که هر واژه یک فیلد است.

الگوها و کنش‌ها، ادامه

می‌توان الگو را حذف کرد، که در این صورت کنش برای هر رکورد ورودی ارزیابی می‌شود.

می‌توان کنش را حذف کرد، که در این صورت کنش پیش‌فرض چاپ رکورد جاری است.

الگوهای ویژه

دو الگوی ویژه وجود دارد که اغلب استفاده می‌شوند.

  • BEGIN کنش مرتبط را پیش از آنکه هر ورودی مصرف شود ارزیابی می‌کند.
  • END کنش مرتبط را پس از آنکه تمام ورودی مصرف شد ارزیابی می‌کند.

متغیرهای فیلد

به فیلدها با $1، $2، $3 و غیره ارجاع می‌دهید.

رکورد جاری $0 است.

Caution

برای صراحت، این‌ها به‌معنای دقیق کلمه «متغیر» نیستند. $ را می‌توان یک عملگر در نظر گرفت که مقدار شماره‌ی فیلد داده‌شده را برمی‌گرداند. در مفاهیم بعدی بیشتر به این موضوع می‌پردازیم.

چند متغیر توکار دیگر هم هستند که زیاد استفاده می‌شوند.

متغیرهای توکاری که تجزیه‌ی ورودی را کنترل می‌کنند

  • RS جداکننده‌ی رکورد ورودی است. همان‌طور که گفته شد، مقدار پیش‌فرض آن خط جدید است.
  • FS جداکننده‌ی فیلد ورودی است.

این متغیرها اغلب در بلوک کنش BEGIN تنظیم می‌شوند.

متغیرهای توکاری که اطلاعات را منتقل می‌کنند

این متغیرها هنگام اجرای برنامه به‌طور خودکار توسط AWK تنظیم می‌شوند.

  • NF تعداد فیلدهای رکورد جاری را ذخیره می‌کند.
    • برای به‌دست‌آوردن مقدار آخرین فیلد، از $NF استفاده کنید.
  • NR شماره‌ی رکورد جاری را ذخیره می‌کند.
    • وقتی چند فایل ورودی پردازش می‌شوند، NR تعداد کل رکوردهای پردازش‌شده تا این لحظه را نگه می‌دارد.
  • FNR شماره‌ی رکورد جاری در فایل ورودی جاری را ذخیره می‌کند.
    • برای روشن‌شدن تفاوت میان NR و FNR، یک اصطلاح رایج AWK را می‌آوریم.
      NR == FNR {action}
      
      این یعنی «اگر شماره‌ی رکورد انباشته با شماره‌ی رکورد فایل جاری برابر باشد.» این تنها برای رکوردهای نخستین فایل ورودی می‌تواند درست باشد.

درستی

AWK همان مفهوم درستی را به کار می‌برد که C به کار می‌برد:

  • عدد 0 «غلط» است.
  • هر عدد دیگری «درست» است.

از آنجا که AWK یک زبان پردازش متن است، مقادیر درستی به رشته‌ها هم گسترش یافته‌اند.

  • یک رشته‌ی خالی "" «غلط» است.
  • هر رشته‌ی ناتهی «درست» است.
Note

AWK همان مفهوم درستی را به کار می‌برد که C به کار می‌برد

AWK در دهه‌ی ۱۹۷۰ در آزمایشگاه‌های بل پدید آمد، در همان محیطی که C اختراع شد. C تأثیر زیادی بر نحوه‌ی نگارش AWK داشت.

Caution

یک نکته‌ی عجیب که باید مراقبش باشید

  • عدد 0 «غلط» است.
  • رشته‌ی ناتهی "0" «درست» است!

در مفاهیم بعدی بیشتر به انواع داده در AWK می‌پردازیم.

توضیحات

توضیحات با نویسه‌ی # شروع می‌شوند و تا پایان خط ادامه دارند.

چگونه به awk ورودی دهیم

awk می‌تواند ورودی را از فایل‌ها یا از ورودی استاندارد بخواند. هر یک از این روش‌ها کار می‌کند.

awk '/regex/ {print $1}' file1 file2 ...

awk '/regex/ {print $1}' < file

some_command_here | awk '/regex/ {print $1}'

مثال‌ها

در سیستم‌های شبه‌یونیکس، /etc/passwd اطلاعاتی درباره‌ی کاربران دارد. هر کاربر در یک خط جداگانه توصیف می‌شود، و فیلدها با دونقطه از هم جدا می‌شوند.

برای فهرست‌کردن نام‌های کاربری:

awk '
    BEGIN { FS = ":" }
    { print $1 }
' /etc/passwd

توجه کنید که کنش {print $1} الگویی ندارد، بنابراین برای هر رکورد اجرا می‌شود.

اگر بخواهیم خروجی را تنها به کاربرانی محدود کنیم که از bash به‌عنوان پوسته‌ی ورود خود استفاده می‌کنند، می‌توانیم این کار را بکنیم:

awk '
    BEGIN { FS = ":" }
    $7 == "/bin/bash" { print $1 }
' /etc/passwd

چند مثال دیگر

چند برنامه‌ی awk که همان نتایج برخی دستورهای رایج یونیکس را تولید می‌کنند.

  • نمایش یک فایل

    cat file.txt
    
    awk '1' file.txt
    
  • جست‌وجوی الگوها در یک فایل

    grep 'foo.*bar' file.txt
    
    awk '/foo.*bar/' file.txt
    
  • نمایش تنها چند خط از ابتدای یک فایل

    head -n 20 file.txt
    
    awk '
        1
        NR == 20 {exit}
    ' file.txt
    
  • جایگزینی متن در یک فایل

    sed 's/foo/bar/' file.txt
    
    awk '{sub(/foo/, "bar")};1' file.txt
    # or more readably
    awk '
        {
            sub(/foo/, "bar")
            print
        }
    ' file.txt
    
ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

اصول را یاد بگیرید