סיכום כל הארגומנטים עם shift

24/11/2022

הפקודה shift ב bash "מזיזה" את הארגומנטים מקום אחד שמאלה, כך ש $1 נמחק, $2 הופך ל $1, $3 הופך ל $2 וכך הלאה. הסקריפט הבא מציג דוגמת שימוש פשוטה ב shift שפשוט מדפיסה את שני הארגומנטים הראשונים שקיבלה:

#!/bin/bash

echo $1
shift
echo $1

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

#!/bin/bash

[[ $# == 0 ]] && exit 0

echo $1
shift
exec $0 "$@"

או בחזרה לכותרת - אם אני רוצה לסכום את כל הארגומנטים שהסקריפט קיבל אני יכול לנסות שוב ברקורסיה, והפעם אני מעביר ל shift את המספר 2, מה שגורם לו להזיז את הארגומנטים בשני מקומות:

#!/bin/bash

if [[ $# == 1 ]]
then
        echo $1
        exit 0
fi

(( sum = $1 + $2 ))

shift 2

exec $0 $sum "$@"

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

while getopts "c:o:l" opt; do
  case $opt in
    c)
      COUNT=$OPTARG;;
    o)
      OUTFILE=$OPTARG;;
    l)
      PADDING=1;;
  esac
done

shift $((OPTIND-1))

התוכנית השתמשה ב getopts כדי לפענח את כל הארגומנטים שמתחילים במינוסים, כולל את הפרמטרים ש"תפסו" ערכים אחריהם (במקרה שלנו c ו o), ואז "הזיזה" את כל הארגומנטים כדי להיפטר מכל אלה שפוענחו על ידי getopts כך שהמשך הקוד יכול לעבוד עם $1, $2 וכן הלאה.

נ.ב. למרות שרקורסיות זה כיף, שווה לזכור שב bash אפשר לרוץ על כל הארגומנטים עם לולאת for פשוטה - רק צריך לוותר על ה in. לדוגמה חישוב סכום של כל הארגומנטים יהיה פשוט:

#!/bin/bash

for arg
do
  (( sum += arg ))
done

echo $sum