Bash Tips
985 subscribers
14 photos
4 files
45 links
רוצים להשתמש בלינוקס אבל לא ממש מכירים את הכלים שהיא מספקת לעבודה?

בערוץ הבא תמצאו אוסף טיפים שימושיים ב-Bash והכרות עם כלים שונים שעשויים לחסוך מאמץ ועבודה בכתיבת סקריפטים ומימוש אוטומציות.
Download Telegram
לקבל ערך indirect references
רמת קושי: #advanced

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

$ cat test.sh

key="value"
myvar="key"

echo "\${key} = ${key}"
echo "\${myvar} = ${myvar}"
echo "\${!myvar} = ${!myvar}"


זהו הקוד שלנו יש לנו 2 משתנים, האחד מכיל ערך והשני מכיל את השם של המשתנה הראשון, באש מאפשרת לנו לקבל את לקבל את הערך של המשתנה הראשון על ידי קריאה של המשתנה השני, כל זאת על ידי שימוש ב indirect expansion, זה נראה כך

$ bash test.sh
${key} = value
${myvar} = key
${!myvar} = value


מה היה לנו כאן?
שני השורות הראשונות דיי ברורות לנו, אנו קוראים למשתנה שמכיל מחרוזת והמחרוזת מודפסת, בשורה האחרונה לעומת זאת מתרחש החלק המעניין, אנו מדפיסים את השם של המשתנה (myvar) עם !, וזה בעצם שולח את באש לחפש אם קיים לה בזיכרון שם של משתנה בשם של המחרוזת (key), במידה והתשובה היא כן אנו נקבל את הערך של אותו משתנה (value) כאילו קראנו למשתנה עצמו.

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

$ cat test.sh
read -p "please enter exist ENV vartiable name: " var
echo "variable name ${var}: ${!var}"

$ bash test.sh
please enter exist ENV vartiable name: SHELL
variable name SHELL: /bin/bash


#indirect_references
#indirect_expansion

@bash_tips
👍1
להעביר מערכים לפונקציה
רמת קושי: #advanced

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

$ cat test.sh
myFunc(){
echo $1
echo $2
}
myFunc one two

$ bash test.sh
one
two

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

myFunc(){
echo $1
echo $2
}
myList=(one two)
myFunc ${myList[@]}

$ bash test.sh
one
two

נוכל לנסות לאסוף את כל הערכים שמגיעים לפונקציה ולהגדיר אותם כמערך על ידי שימוש ב ${@} בפונקציה, אבל זה יכול לעבוד רק בתנאי שאין לנו עוד ערכים אחרים להעביר לפונקציה

myFunc(){
echo ${@}
echo $2
}
myList=(one two)
myFunc ${myList[@]} new_parameter

$ bash test.sh
one two new_parameter
two

בעיה, איך בעצם כן אפשר להעביר מערכים לפונקציות בבאש?
מעבר לאפשרות של משתנים גלובלים להלן 2 דרכים שונות להתמודד עם הבעיה

פתרון 1: העברת מחרוזות
הפתרון הראשון הוא פשוט להעביר את המערך כמחרוזת ואז בפונקציה עצמה ליצור מערך חדש על ידי העברה של המחרוזת ל read כפי שראינו בעבר.

myFunc(){
read -r -a arr1 <<< ${1}
read -r -a arr2 <<< ${2}
declare -p arr1 arr2
}
arr1=(aaa bbb ccc)
arr2=(ddd eee fff)

myFunc "${arr1[*]}" "${arr2[*]}"

$ bash test.sh
declare -a arr1=([0]="aaa" [1]="bbb" [2]="ccc")
declare -a arr2=([0]="ddd" [1]="eee" [2]="fff")

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

פתרון 2: indirect references
את indirect references הכרנו בפוסט הקודם, בגדול מה שזה אומר הוא שניתן לקבל איזה ערך של משתנה שנרצה מאיזה חלק בתוכנית על ידי חיפוש שם המשתנה בזיכרון התוכנית

$ cat test.sh
myFunc(){
func_arr1=( "${!1}" )
func_arr2=( "${!2}" )
declare -p func_arr1 func_arr2
}

arr1=("aaa" "bbb space" "ccc")
arr2=("ddd" "eee" "fff")
myFunc arr1[@] arr2[@]

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

$ bash test.sh
declare -a func_arr1=([0]="aaa" [1]="bbb space" [2]="ccc")
declare -a func_arr2=([0]="ddd" [1]="eee" [2]="fff")

#read
#array
#function
#arguments
#indirect_references

@bash_tips