8 min. read

פרק קודם:

פייתון 14 - מודולים

מה נלמד

  • מה זה רגקס - Regex
  • איך עובדים עם רגקס
  • כתיבת קוד בעזרת רגקס
  • טיפים לכתיבת רגקס טוב

הקדמה

טקסט קיים בכל מקום - אפילו מילים אלו זה טקסט שאתם קוראים!
בתוכנה אנו כותבים וקוראים תוכן טקסטואלי - אלו מילים קריאות לשפה האנושית ולא 0 או 1.

בפרק “שפה בינארית וקבצים בינאריים” אני מסביר על מידע שאינו טקסטואלי.

פייתון 12 - קבצים בינאריים

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

  • כתובת מייל
    name@domain.extension
  • כתובת IP:
    192.168.1.1
  • סיסמא חזקה:
    f&s@lam1MM

אם נפרט את תוכן התבנית, נוכל לחלק את התבניות בצורה הזו:

תבנית סוג תבנית פירוט
user@email.extension אימייל אותיות אנגליות קטנות וגדולות, מספרים, התו @ ואחר כך שוב אותיות אנגליות קטנות או גדולות עם אפשרות לנקודה או תווים כמו - וכדו’…
192.168.1.1 אייפי 4 מספרים בין 0 ל 255 שמופרדים בנקודה
f&s@lam1MM סיסמא חזקה אותיות אנגליות קטנות וגדולות, מספרים ותווים מיוחדים כמו @

Regular Expressions - Regex - רגקס

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

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

הרצה ובדיקה של ביטוי רגקס

אני משתמש באתר הבא כדי לכתוב רגקס,
האתר מכיל מקום לרגקס וטקסט דוגמא.

https://regex101.com/

למשל כאן אני בודק את התבנית abcdef.

קודם כל נכיר את חוקי הרגקס וכיצד כותבים אותו, לאחר מכן נראה איך נכתוב את הקוד בפייתון!

שימו ❤:

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

חוקיי רגקס

כל תו מאמת את עצמו

כל תו ניתן לאמת כאשר התו הזה מופיע.
הרגקס ‘abc’ יימצא כל ‘abc’.

רגקס טקסט תוצאה
abc abcdefg abc
b5 afrb5g b5

הוספת סלאש כדי להגדיר תווים מיוחדים

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

1
\.

זה אומר “תרתי משמע אני רוצה נקודה”.
לעומת

1
.

שאומר כל תו (מיד נסביר על תווים מיוחדים).

זה נכון לכל התווים המיוחדים המוגדרים פה כמו סוגריים ותווים כמו: ^, ?, $ וכדו’…

סוג תווים שונים

קיימים חוקים בסיסיים שנותנים לנו לבחור “סוג תו” כמו האם זה מספר, האם זה אות בשפה וכדו’..

תבנית סוג תבנית Regex דוגמא תקינה
\d תו מספרי מ-0 עד 9 \d\d 25
\w תו מילה - כל מיני תווים שמרכיבים מילים כולל מספרים יכול גם להכיל תווים מכל מיני שפות שונות! \w\w\w אבג
\s תווים מיוחדים כגון רווחים, תווי שורה חדשה, טאבים וכדו’… \w\s\w א ב
\D \d כל דבר שהוא לא \D\D\D abc
\W \w כל דבר שהוא לא \W\W\W 123
\S \s כל דבר שהוא לא \S\S\S abc

הערה חשובה

התו הזה הוא מיוחד כי הוא מוצא תווים שלא רואים אותם, כמו רווחים.
יש תו מאוד חשוב לפייתון שהוא הטאב- הוא מוגדר בצורה שונה לפעמים,
הטאב מוסיף רווח גדול והוא מוגדר כ- “t\“.
או “סלאש טי”.
ככה עושים אותו:

כמו טאב ורווח יש גם תווים מיוחדים לשורה חדשה שהוא נכתב “n\“.

בדוגמא הזו אני מוצא כל מה שיש לו שורה חדשה בין a ל-b.

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

1
2
regexString = '\\t'
regexStringTwo = r'\t'

הסלאש צריך להופיע בתוך המחרוזת, ובגלל שפייתון הסלאש זה תו מיוחד צריך להבדיל אותו.

תרגיל

הריצו את הרגקסים האלו באתר Regex101.
תנסו למצוא דוגמאות שיתאימו עבור הרגקסים הבאים:

1.

1
\w\s\d

2.

1
file_\d\d\d

3.

1
\W\W\W


בדיקת כמות של תווים

ניתן לבדוק כמות תווים ע”י התבניות הבאות:

תבנית משמעות Regex דוגמא תקינה
+ אחד או יותר a+ aa a
? תו אחד או אפס a? a
* אפס או יותר a* aaaaaaa
{2} בדיוק 2 a{2} aa
{2,3} טווח, בדוגמא זה 2 עד 3 a{2,3} aa aaa
{2,} טווח עד אינסוף a{2,} aa aaaaaaaa

קבוצות וטווחים

תבנית משמעות Regex דוגמא תקינה קבוצה
. כל תו שהוא ….. abcde 12345 !@#$%
() מוצא את מה שבתוך הסוגריים ושם את התוצאה בקבוצה שאפשר יהיה לגשת למה שחישפנו a_(.*) a_1231 a_aa a_1231 1231 aa 1231
[] מגדיר טווח של תווים לפי ההגדרה שבתוך הסוגריים [a-z]* avza ffhka abcdefg
[] [1-9]{2,} 11 532
(?) מוצא מה שאחרי הסימן שאלה ולא שומר את הקבוצה
[^] מוצא את מה שלא נמצא בתוך הטווח הזה, בעצם “כל דבר שהוא לא”. [^abc] efgh sdf hlv kom 123
(|) משהו או משהו (a|b) a b a b

Wildcard

זהו מונח שבדרך כלל מתייחס לחיפוש כל תו שהוא.
או בערת רגקס - נקודה כוכבית - .*.
נקודה כוכבית נותנת לנו לחפש כל דבר.

עוגנים

תבנית משמעות Regex דוגמא תקינה
^ תחילת המשפט או הטקסט ^abcdef abcdef
$ סוף השורה או הטקסט [0-9]+$ 555 111

שני העוגנים הכי חשובים זה תחילת המחרוזת וסוף המחרוזת - ככה ניתן להשתמש ברגקס כדי למצוא ביטויים מדוייקים יותר.

תרגיל

תכתבו רגקסים לחיפוש טקסט:

  1. מציאת שם שאורכו 4 תווים באותיות אנגליות קטנות או גדולות

  2. מציאת תוויות של מוצרים אשר מוגדרים כ9 מספרים בין 1 ל 8.

  3. מצאו תאריך בפורמט הבא:
    שנה-חודש-יום.
    למשל:

1
25.2.2021
  1. כתבו רגקס לחיפוש הטקסט הבא:
1
[933]

מורכב משני סוגריים מרובעות עם 3 מספרים בפנים.
5. כתבו רגקס לחיפוש שני קבוצות:

1
AGFA 6641

הקבוצה הראשונה - אותיות אנגליות גדולות בלבד
ואז יש רווח
ואז 4 מספרים מ0 עד 9.


מימוש פייתון - אימות קלט

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

שימו לב ששמתי דולר במקום הסימן @ - והאתר הביא לי סימן כתום שאומר ששמתי מידע לא נכון.
ברגע שאני שם סימן נכון זה כבר לא מופיע:

מימוש תמים לאימות אימייל

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def ValidateEmail(email):
atSignSplit = email.split('@')
if len(atSignSplit) < 2:
return False
site = atSignSplit[1]
dotSplit = site.split('.')
if len(dotSplit) < 2:
return False
else:
return True

emails = [
'iluga@simplycode.co.il',
'iluga$simplycode.co.il'
]
for email in emails:
isValid = ValidateEmail(email)
if isValid:
print(f"Email {email} is valid")
else:
print(f"Email {email} is not valid")

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

הקוד לא ייעבוד כמו שצריך בחלק מהמקרים, מה אם אשים אימייל כזה:

1
iluga@!@$!%^SDADSA.com.il.asasas.asdas

אז הוא ייכתוב:
Email iluga@!$!%^SDADSA.com.il.asasas.asdas is valid

מימוש חכם יותר בעזרת חוקי רגקס

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import re

def ValidateEmail(email):
emailRegex = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
if re.search(emailRegex, email):
return True
return False

emails = [
'iluga@simplycode.co.il',
'a@gmail.com',
'iluga$simplycode.co.il',
'iluga@simplycode . co.il'
]
for email in emails:
isValid = ValidateEmail(email)
if isValid:
print(f"Email {email} is valid")
else:
print(f"Email {email} is not valid")

המודול שנשתמש בו בפייתון נקרא re, קיצור ל-RegularExpression.
המודול מאפשר לנו לחפש על מחרוזות בעזרת המתודות search ו-match.

בדוגמא למעלה קראנו לפונקציה בצורה הזו:
re.search(emailRegex, email)

  • פרמטר 1 - התבנית של הרגקס
  • פרמטר 2 - המחרוזות שעליה אנחנו מחפשים

הדבר השני ששמים לב אליו זה התבנית של הגרקס:

1
emailRegex = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"

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

  • הסימן ^ אומר שזה בודק את תחילת הטקסט - זה נקרא עוגן.
  • הסימן $ אומר שזה סוף הטקסט - זה גם עוגן.

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

1
a = 'a@gmail.com'

אבל עבור הטקסט הזה זה לא:

1
a = '22a: xzx Hello my name is a@gmail.com"

ז”א הרגקס יתחיל לעבוד כבר מהתווים הראשונים - 22a.
ולא רק מ- ‘a@gmail.com‘.

  • הסוגריים המרובעות מאגדות חוקים ל”חוק אחד”.

  • המקף ‘-‘ אומר שיש לנו התחלה וסוף,
    בביטוי כמו [a-z]+ אנו מורים לחפש אחת או יותר אותיות אנגליות קטנות בלבד!
    אותיות כמו c, g, k, u ייעברו את החוק כי הם בין האותיות שהגדרנו - a עד z.
    כדי לתפוס אותיות גדולות אנחנו צריכים להגדיר גם כן את החוק הזה לאותיות גדולות.
    [a-zA-Z]+ - ייתפוס גם אותיות גדולות.

שימו לב שביטוי כמו [az]+ יתפוס רק את a ו-z.

זה עובד גם על תווי מספר, הגדרנו שמחרוזות שמכילות גם 0 עד 9 גם ייעברו.
שימו לב שאין צורך בלהגדיר 10-99 וכאלו כי אנחנו מגדירים סוג תו שמופיע כמות פעמים.
אז למשל הרגקס:

1
[0-9]+

אומר התווים מ0 עד 9 אחד פעמים או יותר, אז כל המספרים האלו ייעברו:
0, 9, 99, 12012, 37412, 6312

  • וסימנים כמו _ + . - בתוך הסוגריים המרובעות אומרים תווים רגילים, תרתי משמע התווים.
  • הסימן ‘+’ מחוץ לסוגריים אומר “אחד או יותר”.
    כפי שאמרתי הסוגריים המרובעות הופכות את כל החוקים הפנימיים לחוק אחד.
    ואז הפלוס הופך את כל החוק הזה ל-האם מופיע אחד מהחוקים או יותר.

זה בשביל לתפוס מחרוזות כמו:
‘a’, ‘a.b’ , ‘a.c’
זאת מכיוון שהרבה אימייל כתובים כשם פרטי, נקודה ואז שם משפחה.

שימו לב שיש עוד שני איגודים כאלו - בורוד וצהוב.

הסימן @ מופיע לנו ככה והוא אומר תרתי משמע התו @. אם יופיע שם תו אחר כגון דולר-$ זה לא ייעבוד.

*
הנקודה כחוק רגקס אומר כל תו אפשרי:

למשל הרגקס:

1
a.

יחזיר כל דבר תו שיש לו בהתחלה a, למשל:
ab, a1, a-, a_, aX, a$ וכדו’…

פונקציות חיפוש בפייתון

כמו שכתבנו למעלה - קודם כל אנחנו מייבאים את המודול של רגקס לקוד:

1
import re

findall

הפונקציה הזו מחזירה ברשימה את כל התוצאות:

1
2
3
4
5
6
7
import re

text = '12 11 66 aa 77'

results = re.findall('[0-9]+',text)

print(results)

split

הפונקציה מפצלת את המחרוזת ע”פ החיפוש,
למשל לעשות פיצול ע”י רווחים במשפט:

1
2
3
4
5
6
7
import re

text = 'Never put a sock in a toaster'

results = re.split('\s',text)

print(results)

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

ניגשים למשתנה בעזרת הנקודה
למשל:

1
2
3
4
5
6
7
8
9
import re

txt = '111 222 333'
match = re.search('([0-9]+)\s([0-9]+)\s([0-9]+)', txt)

print(match.groups())
print(match.group(0))
print(match.group(1))
print(match.group(2))

אנחנו יכולים לגשת לרשימת הקבוצות - זה חוזר אלינו כ-Tuple.
הקבוצה הראשונה היא כל המחרוזת שנמצאה כולל כל הקבוצות.
ואז הקבוצה הראשונה באינדקס הראשון - 1 זוהי הקבוצה הכי ראשונה, ואז 2 ואז 3.
תריצו את הקוד ותראו מה יוצא!

sub

הפונקציה מחליפה את כל הטקסט שהיא מצאה במחרוזת אחרת.

1
2
3
4
5
6
7
8
9
import re

txt = 'Hello _____, My congratulations on your new job _____, Regards, your cousin.'

replaceTo = 'Bob'

result = re.sub('\_{5}', replaceTo ,txt)

print(result)

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

Flags

ניתן להוסיף פרמטר נוסף לחלק מהפונקציות שנקרא “דגלים”.
את הדגלים ניתן להוסיף בעזרת האופרטור “ועוד” שכותבים אותו כקו ישר |.

דגל משמעות
re.IGNORECASE מתעלם מאותיות גדולות או קטנות
re.LOCALE משתמש בשפה המקומית של המחשב
re.MULTILINE מחפש גם בין שורות
re.DOTALL הנקודה מוצאת גם שורות חדשות
re.VERBOSE ניתן להשתמש בהערות בתוך הרגקס
re.UNICODE מאפשר להשתמש בסט התווים

יש לנו את השימוש המקוצר ולידו את השימוש הארוך (איך שנוח לכם להשתמש).

1
2
3
4
import re

txt = '111 222 333'
match = re.search('([0-9]+)\s([0-9]+)\s([0-9]+)', txt, re.IGNORECASE | re.MULTILINE)

תרגיל

  1. אחד המקרים הנפוצים שאנחנו רוצים לחפש בטקסט זה לוגים.
    לוג הוא קובץ המכיל שורות כאשר כל שורה מכילה מידע והודעה אשר מטרתה להודיע באיזו שעה משהו קרה בתוך התוכנה שלנו.
    דוגמא לשורות לוג שנעבד:
1
2
3
4
25-02-2021 12:00:01.000 Info System.cs (25): Hello World
25-02-2021 12:00:01.000 Debug ImageTranslator.cs (58): Image Translator initialized
25-02-2021 12:00:01.001 Debug ImageSender.cs (90): Sender looking for device
25-02-2021 12:00:01.001 Error ImageSender.cs (94): Sender couldn't find device

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

  • עליכם למצוא מהם החלקים השונים של הלוג
  • לכתוב רגקס שיתאים לכל החלקים שלו
  • בונוס: תשמרו את השורות האלו לקובץ שנקרא “System.log” ואז תקראו ממנו שורה שורה.

2.
לדף אינטרנט ששומר תגובות של אנשים דרושה פונקציה שתנקה את הקלט של משתמש.
מכיוון שקלט של משתמש הוא לא בטוח - חייבים לוודא שהוא בטוח להצגה אחרת יהיו לנו בעיות אבטחה כגון XSS.
תקראו על זה בויקיפדיה

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

1
2
<div> My Attack</div>
<script src="https://someMaliciousSite.com/myscripts.js"></script>

אנחנו רוצים לתפוס את כל התגיות התחלה ותגיות הסיום ולהחליף אותם בטקסט ריק.

  • איך נראית תגית התחלה וסיום?
  • מהו הרגקס עבור זיהוי כל התגיות האלו?
    כרגע נניח שהתגיות עם תחילית וסיומת - ז”א אין תגיות שיש להם רק התחלה ללא תגית הסוף.


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

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

פייתון 16 - מחלקות חלק א

אהבתם? מוזמנים להביע תמיכה כאן: כוס קפה