כיצד להשתמש בשפת AWK לעיבוד טקסט ב־Linux

הקדמה

כלי Linux בדרך כלל מתאפיינים בפילוסופיה של יוניקס לעיצוב. מודעים לשימוש בכלים קטנים, בשימוש בקבצי טקסט פשוטים כקלט וכפלט, ולפעול באופן מודולרי. כתוצאה ממנה, יש לנו פונקציות עיבוד טקסט מעולות עם כלים כמו sed ו־awk.

awk הוא גם שפת תכנות ועובד טקסט שבאפשרותך להשתמש בו כדי לעבד נתוני טקסט בדרכים מאוד שימושיות. במדריך זה, תלמד כיצד להשתמש בכלי השורת פקודה awk וכיצד להשתמש בו לעיבוד טקסט.

תחביר בסיסי

פקודת awk כלולה כבר במערכות Linux המודרניות בצורה ברירת מחדל, לכן אין צורך להתקין אותה כדי להתחיל להשתמש בה.

awk היא הכי שימושית כאשר מתמודדים עם קבצי טקסט המסודרים בדרך צפויה. למשל, היא מצוינת בפענוח ובעיבוד של נתונים טבלאיים. היא פועלת על בסיס שורה-אחר-שורה ועוברת דרך כל הקובץ.

באופן ברירת המחדל, היא משתמשת ברווחים (רווחים, טאבים, וכו') כדי להפריד שדות. מזל שרבים מקבצי התצורה במערכת ה־Linux שלך משתמשים בתבנית זו.

הפורמט הבסיסי של פקודת awk הוא:

  1. awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse

ניתן להתעלם מחלק החיפוש או מחלק הפעולה בפקודת awk. ברירת המחדל היא להדפיס את כל השורות המתאימות.

אם חלק החיפוש אינו נתון, awk מבצע את הפעולה הרשומה על כל שורה.

אם שניהם נתונים, awk משתמש בחלק החיפוש כדי להחליט האם השורה הנוכחית מתאימה לתבנית, ואז מבצע את הפעולות על התאמות.

בפורמט הכי פשוט שלה, אפשר להשתמש ב־awk כמו ב־cat כדי להדפיס את כל השורות של קובץ טקסט למסך.

צור קובץ favorite_food.txt שמפרט את המאכלים המועדפים של קבוצת חברים.

  1. echo "carrot sandy
  2. wasabi luke
  3. sandwich brian
  4. salad ryan
  5. spaghetti jessica" > favorite_food.txt

כעת השתמש בפקודת awk כדי להדפיס את הקובץ למסך.

  1. awk '{print}' favorite_food.txt

תראה את הקובץ מודפס למסך.

Output
carrot sandy wasabi luke sandwich brian salad ryan spaghetti jessica

זה לא מאוד שימושי. בוא ננסה את יכולות הסינון של awk על ידי חיפוש בקובץ לטקסט "חול".

  1. awk '/sand/' favorite_food.txt
Output
carrot sandy sandwich brian

כפי שתראה, awk מדפיס כעת רק את השורות שיש בהם את התווים "חול".

באמצעות ביטויים רגולריים, אפשר לכוון חלקים ספציפיים של הטקסט. כדי להציג רק את השורה שמתחילה באותיות "חול", השתמש בביטוי הרגולרי ^חול:

  1. awk '/^sand/' favorite_food.txt

הפעם, מוצגת רק שורה אחת:

Output
sandwich brian

באופן דומה, אפשר להשתמש בחלק הפעולה כדי לציין אילו חלקי מידע אתה רוצה להדפיס. לדוגמה, כדי להדפיס רק את העמודה הראשונה, השתמש בפקודה הבאה:

  1. awk '/^sand/ {print $1;}' favorite_food.txt
Output
sandwich

ניתן להתייחס לכל עמודה (כפי שמופרדת על ידי רווחים) על ידי משתנים המשוייכים למספר העמודה שלהן. לדוגמה, העמודה הראשונה היא $1, השנייה היא $2, ואפשר להתייחס לכל השורה באמצעות $0.

משתנים פנימיים ותבנית מורחבת

הפקודה awk משתמשת במשתנים פנימיים כדי להקצות מידע מסוים בעת עיבוד קובץ.

המשתנים הפנימיים שהפקודה awk משתמשת בהם הם:

  • FILENAME: מתייחס לקובץ הקלט הנוכחי.
  • FNR: מתייחס למספר הרשומה הנוכחית יחסית לקובץ הקלט הנוכחי. לדוגמה, אם יש לך שני קבצי קלט, זה יגיד לך את מספר הרשומה של כל קובץ בנפרד במקום כסכום.
  • FS: המפריד הנוכחי שמשמש לציון כל שדה ברשומה. כברירת מחדל, הוא מוגדר לרווחים.
  • NF: מספר השדות ברשומה הנוכחית.
  • NR: מספר הרשומה הנוכחית.
  • OFS: מפריד השדות למידע המוצג. לדוגמה, ברירת המחדל היא רווחים.
  • ORS: מפריד הרשומות למידע המוצג. לדוגמה, ברירת המחדל היא תו חדש שורה.
  • RS: המפריד רשומות שמשמש להבחנה בין רשומות נפרדות בקובץ הקלט. בדרך כלל, זהו תו שורה חדשה.

ניתן לשנות את ערכי המשתנים הללו כרצונך כדי להתאים אותם לצרכי הקבצים שלך. בדרך כלל אתה עושה זאת בשלב האתחול של עיבודך.

זה מביא אותנו לעקרון חשוב נוסף. תחביר ה־awk קצת יותר מורכב ממה שהשתמשת בו עד כה. ישנם גם בלוקי BEGIN ו־END אופציונליים שיכולים להכיל פקודות לביצוע לפני ואחרי עיבוד הקובץ, בהתאמה.

זה משנה את תחביר השפה הרחב שלנו למשהו דומה לזה:

  1. awk 'BEGIN { action; }
  2. /search/ { action; }
  3. END { action; }' input_file

המילים המפתח BEGIN ו־END הן קבוצות תנאים ספציפיות, בדומה לפרמטרי החיפוש. הן מתאימות לפני ואחרי שהמסמך עבר עיבוד.

זה אומר שתוכל לשנות חלק מהמשתנים הפנימיים בקטע ה־BEGIN. לדוגמה, קובץ ה־/etc/passwd מופרד בין שדותיו על ידי נקודות שבירה (:) במקום רווח לבן.

כדי להדפיס את העמודה הראשונה של קובץ זה, הרץ את הפקודה הבאה:

  1. awk 'BEGIN { FS=":"; }
  2. { print $1; }' /etc/passwd
Output
root daemon bin sys sync games man . . .

ניתן להשתמש בבלוקי BEGIN ו־END כדי להדפיס מידע אודות השדות שאתה מדפיס. השתמש בפקודה הבאה כדי להמיר את הנתונים מהקובץ לטבלה, מסודרת לפי טאבים באמצעות \t:

  1. awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
  2. {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
  3. END { print "---------\nFile Complete" }' /etc/passwd

תראה את הפלט הזה:

Output
User UID GID Home Shell -------------- root 0 0 /root /bin/bash daemon 1 1 /usr/sbin /bin/sh bin 2 2 /bin /bin/sh sys 3 3 /dev /bin/sh sync 4 65534 /bin /bin/sync . . . --------- File Complete

כפי שניתן לראות, ניתן לפורמט דברים באופן נעים על ידי השימוש בתכונות של awk.

כל אחת מהאזורים המורחבים אופציונליים. למעשה, האזור העיקרי לפעולה עצמו הוא אופציונלי אם נגדיר אזור אחר. לדוגמה, ניתן לעשות דברים כמו כן:

  1. awk 'BEGIN { print "We can use awk like the echo command"; }'

ותראו פלט זה:

Output
We can use awk like the echo command

כעת נסתכל על איך לחפש טקסט בתוך שדות של הפלט.

חיפוש שדות וביטויים מורכבים

באחת מהדוגמאות הקודמות, הדפסת את השורה בקובץ favorite_food.txt שהתחילה ב-"sand". הייתה זו משימה קלה מאחר וחיפשת את תחילת השורה כולה.

מה קורה אם ברצונך לגלות האם דפוס החיפוש התואם תחילת שדה במקום?

יצירת גרסה חדשה של קובץ favorite_food.txt שמוסיפה מספר פריט לפני אוכל כל אדם:

  1. echo "1 carrot sandy
  2. 2 wasabi luke
  3. 3 sandwich brian
  4. 4 salad ryan
  5. 5 spaghetti jessica" > favorite_food.txt

אם ברצונך למצוא את כל המזונות מתוך קובץ זה שמתחילים ב-"sa", תוכל לנסות משהו דומה לזה:

  1. awk '/sa/' favorite_food.txt

זה מציג את כל השורות שמכילות "sa":

Output
1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan

כאן, אתה מתאים לכל הופעה של "sa" במילה. זה כולל דברים כמו "ווסאבי" שיש לה את הדפוס באמצע, או "סנדי" שאינו בעמודה שבה ברצונך. במקרה זה אתה רק מעוניין במילים שמתחילות ב-"sa" ב- עמוד ה-שני.

ניתן להגדיר ל־awk לחפש רק בתחילת העמוד השני באמצעות הפקודה הזו:

  1. awk '$2 ~ /^sa/' favorite_food.txt

כפי שניתן לראות, זה מאפשר לנו לחפש רק בתחילת העמוד השני עבור התאמה.

חלק ה־field_num ~ מציין כי awk צריך להתייחס רק לעמודה השנייה.

Output
3 sandwich brian 4 salad ryan

ניתן בקלות לחפש גם אחר דברים שאינם מתאימים על ידי כלול התו "!" לפני הטילדה (~). הפקודה הזו תחזיר את כל השורות שאין להן מזון שמתחיל ב־"sa":

  1. awk '$2 !~ /^sa/' favorite_food.txt
Output
1 carrot sandy 2 wasabi luke 5 spaghetti jessica

אם תחליטו מאוחר יותר שאתם רק מעוניינים בשורות שאינן מתחילות ב־"sa" ומספר הפריט הוא פחות מ־5, תוכלו להשתמש בביטוי מורכב כמו זה:

  1. awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt

הפקודה מציגה מספר רעיונות חדשים. הראשון הוא היכולת להוסיף דרישות נוספות עבור התאמה של השורה באמצעות האופרטור &&. באמצעות זאת, ניתן לשלב מספר של תנאים כדי שהשורה תותאם. במקרה זה, אתה משתמש באופרטור זה כדי להוסיף בדיקה שערך העמודה הראשונה קטן מ־5.

תראו את הפלט הזה:

Output
1 carrot sandy 2 wasabi luke

ניתן להשתמש ב־awk לעיבוד קבצים, אך ניתן גם לעבוד עם הפלט של תוכניות אחרות.

עיבוד הפלט מתוכניות אחרות

ניתן להשתמש בפקודת awk כדי לפענח את פלט התוכניות האחרות במקום לציין שם קובץ. לדוגמה, ניתן להשתמש ב־awk כדי לפענח את כתובת ה־IPv4 מהפקודה ip.

הפקודה ip a מציגה את כתובת ה־IP, כתובת השידור ומידע נוסף על כל ממשקי הרשת במחשב שלך. כדי להציג את המידע עבור הממשק הנקרא eth0, השתמש בפקודה זו:

  1. ip a s eth0

תראה את התוצאות הבאות:

Output
2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever

ניתן להשתמש ב־awk כדי לגשת אל שורת ה־inet ולאחר מכן להדפיס רק את כתובת ה־IP:

  1. ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'

הדגל -F אומר ל־awk להפריד לפי נקודותיים לצדדים או רווחים באמצעות הביטוי הרגולרי [\/ ]+. זה מפריד את השורה inet 172.17.0.11/16 לשדות נפרדים. כתובת ה־IP נמצאת בשדה השלישי מכיוון שהרווחים בתחילת השורה גם מחשבים כשדה, מאחר שהפרדת לפי רווחים וגם לפי נקודותיים. שים לב ש־awk טיפל ברווחים רצופים כרווח יחיד במקרה זה.

הפלט מציג את כתובת ה־IP:

Output
172.17.0.11

תמצא הרבה מקומות שבהם ניתן להשתמש ב־awk כדי לחפש או לפענח את פלט של פקודות אחרות.

סיכום

עכשיו, אמור לך להבין באופן בסיסי כיצד ניתן להשתמש בפקודת awk כדי לשנות, לעצב, ולהדפיס באופן בררת מחדל קבצי טקסט וזרמי טקסט. Awk הוא נושא רחב יותר, והוא למעשה שפת תכנות שלמה עם הקצאת משתנים, מבני בקרה, פונקציות מובנות, ועוד. ניתן להשתמש בו בתוך סקריפטים שלך כדי לעצב טקסט בדרך אמינה.

כדי ללמוד עוד על awk, ניתן לקרוא את הספר החינמי בדומיין הציבורי של יוצריו שמסביר בפרטיות רבה יותר.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-the-awk-language-to-manipulate-text-in-linux