פרק קודם:
פייתון 14 - מודוליםטקסט קיים בכל מקום - אפילו מילים אלו זה טקסט שאתם קוראים!
בתוכנה אנו כותבים וקוראים תוכן טקסטואלי - אלו מילים קריאות לשפה האנושית ולא 0 או 1.
בפרק “שפה בינארית וקבצים בינאריים” אני מסביר על מידע שאינו טקסטואלי.
פייתון 12 - קבצים בינארייםתוכן טקסטואלי מכיל שפה אנושית העוזרת לנו להבין את תוכן המידע.
ובדרך כלל נמצא את המידע בתבניות קריאות ומובנות:
ננסה להבין את מהות התוכן ולבנות תבנית מסודרת:
תבנית | סוג תבנית | פירוט |
---|---|---|
“user@email.extension“ | אימייל | אותיות אנגליות קטנות וגדולות, מספרים, התו @ ואחר כך שוב אותיות אנגליות קטנות או גדולות עם אפשרות לנקודה או תווים כמו - וכדו’… |
192.168.1.1 | אייפי | 4 מספרים בין 0 ל 255 שמופרדים בנקודה |
f&s@lam1MM | סיסמא חזקה | אותיות אנגליות קטנות וגדולות, מספרים ותווים מיוחדים כמו @ |
למשל ניקח את המייל וננסה לבנות ממנו תבנית שניתן לחזור עליה:
מייל מורכב משני חלקים - החלק שלפני התו @
והחלק שאחריו.
החלק שלפני מסמן לנו יישות קיימת.
החלק השני מסמן לנו איפה היישות הזו קיימת.
נפשט את המייל ונניח שהוא רק באנגלית תקנית.
זיהינו כמה דברים במייל:
@
אותיות גדולות וקטנות נראות ככה:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
עכשיו ננסה לקצר את זה ונאמר פשוט:a-zA-Z
.
איך נייצג מספרים?012345679
או פשוט יותר:0-9
.
עכשיו אנחנו צריכים להוסיף סימן שיגיד לנו כמה פעמים התו יופיע.
אם רק נאמר 0-9
זה לא אומר לנו כמה פעמים זה אמור להופיע!
אז נניח שהתו *
יגיד לנו 0 או יותר
.
אז לייצג ביחד נוכל לומר:a-ZA-Z0-9*
אבל פה מתחילה בעיה - אם נניח יש לי 2 תווים באנגלית ותו מספרי איך אני יודע מהי הכמות שתו יכול להופיע בו?
נפתור את זה בעזרת סוכם אשר אומר אחד מהתווים האלו
.
ונשתמש בסוגריים מרובעות בשביל זה:[a-zA-Z0-9]*
ובכך הגענו למוסכמה חברתית שמגדירה את המשפט הבא:יופיע אפס או יותר תווים אשר מוגדרים כתו אנגלי קטן או גדול או תו מספרי
.
וע”י הגיון פשוט הגענו למשפט רגקס תקין!
רגקס זוהי תבנית של תווים שמגדירה כיצד לחפש בתוך טקסט.
ביטוי רגקס הוא מחרוזת שמתארת כיצד טקסט נראה - כמעט כמו ביטוי מתמטי.
כמו ביטויים בתוכנה גם הרגקס הוא פונקציונאלי, עם קבוצות, עוגנים ותווים שמתארים כיצד הרגקס מתנהג.
כפי שראינו ביטויי רגקס הם מאוד לוגיים והם מגדירים חוקים מדוייקים.
אני משתמש באתר הבא כדי לכתוב רגקס,
האתר מכיל מקום לרגקס וטקסט דוגמא.
למשל כאן אני בודק את התבנית 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 | regexString = '\\t' |
הסלאש צריך להופיע בתוך המחרוזת, ובגלל שפייתון הסלאש זה תו מיוחד צריך להבדיל אותו.
הריצו את הרגקסים האלו באתר Regex101.
תנסו למצוא דוגמאות שיתאימו עבור הרגקסים הבאים:
1.
1 | \w\s\d |
2.
1 | file_\d\d\d |
3.
1 | \W\W\W |
1.
1 | a 1 |
2.
1 | file_123 |
3.
1 |
|
ניתן לבדוק כמות תווים ע”י התבניות הבאות:
תבנית | משמעות | 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 |
זהו מונח שבדרך כלל מתייחס לחיפוש כל תו שהוא.
או בערת רגקס - נקודה כוכבית - .*
.
נקודה כוכבית נותנת לנו לחפש כל דבר.
תבנית | משמעות | Regex | דוגמא תקינה |
---|---|---|---|
^ | תחילת המשפט או הטקסט | ^abcdef | abcdef |
$ | סוף השורה או הטקסט | [0-9]+$ | 555 111 |
שני העוגנים הכי חשובים זה תחילת המחרוזת וסוף המחרוזת - ככה ניתן להשתמש ברגקס כדי למצוא ביטויים מדוייקים יותר.
תכתבו רגקסים לחיפוש טקסט:
מציאת שם שאורכו 4 תווים באותיות אנגליות קטנות או גדולות
מציאת תוויות של מוצרים אשר מוגדרים כ9 מספרים בין 1 ל 8.
מצאו תאריך בפורמט הבא:
שנה-חודש-יום.
למשל:
1 | 25.2.2021 |
1 | [933] |
מורכב משני סוגריים מרובעות עם 3 מספרים בפנים.
5. כתבו רגקס לחיפוש שני קבוצות:
1 | AGFA 6641 |
הקבוצה הראשונה - אותיות אנגליות גדולות בלבד
ואז יש רווח
ואז 4 מספרים מ0 עד 9.
1.
1 | [\w]{4} |
2.
1 | [1-8]{9} |
3.
1 | [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4} |
4.
1 | \[[0-9]{3}\] |
מה שמבלבל פה זה שיש לנו שני סוגריים - הראשון מגדיר תרתי משמע את התו של הסוגר,
והסוגר השני הוא כחלק מביטוי רגקס.
הביטוי הפנימי הוא:
1 | [0-9]{3} |
שהוא מחפש בדיוק 3 מספרים בין 0 ל9.
5.
1 | ([A-Z]){4}\s{1}([0-9]{4}) |
בשורה השנייה זה לא מוצא את הטקסט כי יש שם שני רווחים ואנחנו רק רוצים אחד.
בשורה השלישית זה מוצא רק את החלק הראשון כי הגדרנו רק 4 מספרים ולא יותר.
שימו לב שהטקסט מכיל יותר אך הוא מוצא רק את ה-4 תווים הראשונים.
אחד השימושים הכי נפוצים של רגקס זה לבצע אימות על טקסט שמשתמש הביא - למשל :
שימו לב ששמתי דולר במקום הסימן @ - והאתר הביא לי סימן כתום שאומר ששמתי מידע לא נכון.
ברגע שאני שם סימן נכון זה כבר לא מופיע:
1 | def ValidateEmail(email): |
המימוש התמים בודק אם אנחנו יכולים קודם כל לפצל בעזרת התו-@.
לאחר מכן אנחנו בדקנו אם ניתן את הצד הימני לפצל עם נקודה - כי אנחנו מחפשים את התו נקודה.
ואם יש אזי יש לנו אימייל מאומת.
הקוד לא ייעבוד כמו שצריך בחלק מהמקרים, מה אם אשים אימייל כזה:
1 | iluga@!@$!%^SDADSA.com.il.asasas.asdas |
אז הוא ייכתוב:
Email iluga@!$!%^SDADSA.com.il.asasas.asdas is valid
1 | import re |
המודול שנשתמש בו בפייתון נקרא re
, קיצור ל-RegularExpression
.
המודול מאפשר לנו לחפש על מחרוזות בעזרת המתודות search
ו-match
.
בדוגמא למעלה קראנו לפונקציה בצורה הזו:re.search(emailRegex, email)
הדבר השני ששמים לב אליו זה התבנית של הגרקס:
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 |
הפונקציה הזו מחזירה ברשימה את כל התוצאות:
1 | import re |
הפונקציה מפצלת את המחרוזת ע”פ החיפוש,
למשל לעשות פיצול ע”י רווחים במשפט:
1 | import re |
הפונקציה מחזירה סוג משתנה מסוג Match
.
אנחנו בעתיד נעבור על סוגי משתנים מיוחדים כאלו יותר לעומק.
כרגע מה שחשוב הוא זה שאפשר לגשת לסוג משתנה הזה ולמצוא הרבה מידע על סוג התוצאה שלנו מתוך החיפוש רגקס.
ניגשים למשתנה בעזרת הנקודה
למשל:
1 | import re |
אנחנו יכולים לגשת לרשימת הקבוצות - זה חוזר אלינו כ-Tuple
.
הקבוצה הראשונה היא כל המחרוזת שנמצאה כולל כל הקבוצות.
ואז הקבוצה הראשונה באינדקס הראשון - 1
זוהי הקבוצה הכי ראשונה, ואז 2
ואז
3.
תריצו את הקוד ותראו מה יוצא!
הפונקציה מחליפה את כל הטקסט שהיא מצאה במחרוזת אחרת.
1 | import re |
דוגמא פשוטה להחלפה של מחזיק טקסט כלשהו - 5 קוים תחתוניים - בשם.
אפשר לעשות עם זה הרבה דברים מורכבים, אך רגקסים מורכבים הם מאוד קשים להבנה ומאוד סזיפיים.
זה בסדר שלא הכל מובן על ההתחלה, רגקסים זה משהו שבא עם ניסיון ולעשות אותם כמה שיותר.
ניתן להוסיף פרמטר נוסף לחלק מהפונקציות שנקרא “דגלים”.
את הדגלים ניתן להוסיף בעזרת האופרטור “ועוד” שכותבים אותו כקו ישר |
.
דגל | משמעות |
---|---|
re.IGNORECASE | מתעלם מאותיות גדולות או קטנות |
re.LOCALE | משתמש בשפה המקומית של המחשב |
re.MULTILINE | מחפש גם בין שורות |
re.DOTALL | הנקודה מוצאת גם שורות חדשות |
re.VERBOSE | ניתן להשתמש בהערות בתוך הרגקס |
re.UNICODE | מאפשר להשתמש בסט התווים |
יש לנו את השימוש המקוצר ולידו את השימוש הארוך (איך שנוח לכם להשתמש).
1 | import re |
1 | 25-02-2021 12:00:01.000 Info System.cs (25): Hello World |
המטרה שלנו זה לעבד את הלוג כך שיהיה לנו במשתנים שונים כל חלק בלוג.
2.
לדף אינטרנט ששומר תגובות של אנשים דרושה פונקציה שתנקה את הקלט של משתמש.
מכיוון שקלט של משתמש הוא לא בטוח - חייבים לוודא שהוא בטוח להצגה אחרת יהיו לנו בעיות אבטחה כגון XSS.
תקראו על זה בויקיפדיה
כקלט ממשתמש אנחנו רוצים למנוע ממנו לשים תגיות HTML.
כרגע נשאיר את זה מאוד פשוט כדי לא לסבך את התרגיל, תגיות לדוגמא:
1 | <div> My Attack</div> |
אנחנו רוצים לתפוס את כל התגיות התחלה ותגיות הסיום ולהחליף אותם בטקסט ריק.
1 | import re |
דוגמא מאוד קלאסית למה שאפשר לעשות את זה, אפשר לפלטר על סוג מוים של הודעה - למשל אנחנו רוצים רק את השגיאות אז אפשר לחפש את כל השורות שיש בהן Error:
1 | if level == 'Error': |
שימו לב להערה ששמתי בקוד - קודם כל זיהיתי מה מהקבוצות הן הקבוצות שאומרות כל סוג מידע -
תאריך, זמן, רמת לוג וכדו’…
הרגקס עצמו מורכב מתווים מאוד פשוטים, כל מה שהייתי צריך לזהות זה מספרים ותווים באנגלית.
1 | import re |
ניתן לממש רגקס מהסוג הזה בכל מיני צורות אך בחרתי להשתמש בקבוצה ומשהו שנקרא BackReferencing.
אם זיהיתי קבוצה ניתן להשתמש בה בעזרת סלאש ומספר:
1 | \1 |
זוהי הקבוצה הראשונה, וכמובן אפשר לזהות את קבוצה 2, 3 וכדו’…
1 | \2 \3 \4 \5 \6 |
אני יכול להשתמש בזה כדי לזהות את התג הסוגר
1 | <script> </script> |
אבל אם היו כותבים את זה בצורה אפילו טיפה שונה זה לא היה מזהה את זה:
1 | <script </scprit> |
האתר מאפשר דיבוג נרחב לרגקס ותומך בגרסאות שונות שלו בין שפות תכנות!
1 | Generate me regex that validates me hebrew letters where the third one is always a dot and the a group of "ישראל" may be contained in the sentence somewhere |
1 |
|
תמיד תשתמשו בסוגריים מרובעות או מעוגלות על מנת לתחום קבוצות או קבוצות תווים.
שימושי כדי לעבור על שורות רבות בבת אחת.
לעיתים ניתן ברגקס לעבור שורה ושורה או את כל הטקסט בבת אחת.
עבור שימוש כזה נוכל להשתמש בעוגנים על מנת לומר מאיפה השורה מתחילה ואיפה היא מסתיימת:
1 | ^I am.*$ |
הרגקס הנ”ל יציע לנו את כל השורות שמתחילות ב-I am
.
למשל אנחנו רוצים להחליף את שם הפונקציה שלנו וה-IDE
לא עוזר לנו כל כך.
ניתן לבצע את זה בעזרת חיפוש טקסטואלי עם רגקס- איך?
תוכנות כמו - notepad++
מאפשרים לנו להכניס קבוצות שמצאנו בתור הטקסט שיוחלף
הפונקציה שאנו רוצים להחליף אותה:
1 | public void MyFunction(int a){} |
אז נבנה רגקס:
1 | public void MyFunction(\(int a\)\{\}) |
שימו לב ששמנו את התוכן שאחרי המילה בקבוצה - כעת ניתן להחליף בקלות את הכל מבלי סיכונים:
1 | public void MyNewName$1 |
בNotepad++
זה ייגרום להחלפה מלאה של הפונקציה.
למה 1 ולא 0?
בדרך כלל עם קבוצות הספריות ישימו לנו בקבוצה הראשונה את ה”קבוצה הגדולה” שזה בדרך כלל כל המשפט.
ואת הקבוצות האחרות יתחיל לשים מאינדקס 1.
בעזרת (?:.*)
נוכל לא לתפוס את הקבוצה.
למשל (?:[a-z]*)
.
למשל אני רוצה לחפש את כל מה שיש לו תחילית של מספר ונקודה כדי שאוכל לחפש רשימות בתוך טקסט:
1 | 1. A |
אני אוכל לכתוב רגקס כזה:
1 | ^(?<=[0-9]+\.).*$ |
זה יימצא את כל מה שיש לו מספרים עם נקודה לפני שאר הטקסט.
הפוך ניתן להשתמש ב- (?=)
.
למשל אנחנו רוצים את הטקסט הקצר ביותר - נוכל להוסיף סימן שאלה בשביל זה.
1 | a.*?b |
יימצא לנו את הטקסט הקצר בין a ל-b.
1 | (?<name>...) |
רגקסים ייאפשרו להשתמש במוד שנקרא - verbose
.
בפייתון נוכל להשתמש בו כך:
1 | import re |
רגקסים הם נושא מאוד מורכב ואני מקווה שהבנתם לפחות את הבסיס שלו, מה זה ואיך להשתמש בזה בפייתון.
הפרק הזה סוגר לנו את פרקי הבסיס של פייתון.
בפרק הבא נתחיל נושא מורכב שמהווה את מהות התכנות המודרני, תכנות מונחה עצמים!
פייתון 16 - מחלקות חלק א