משתמש:Mad dr/פייתון/מודולים/re: הבדלים בין גרסאות בדף
יצירת דף עם התוכן " נושא עיבוד המידע חשוב מאוד בתכנות, ולעיתים אנו נדרשים לעבד טקסט חופשי שלא מסודר בפורמט כ..." |
(אין הבדלים)
|
גרסה מ־22:23, 21 בספטמבר 2014
נושא עיבוד המידע חשוב מאוד בתכנות, ולעיתים אנו נדרשים לעבד טקסט חופשי שלא מסודר בפורמט כמו json או xml. לעיתים נצטרך להבין לוג או הודעת שגיאה, ולפעמים נראה לסנן את המידע החשוב כדי להשתמש בו בהמשך. (דוגמא טובה לזה נמצאת בדרך בה אפיליקציה וובית, או אתר רגיל, "קורא" את הכתובת שלו, ונגיע לזה כנלמד על טורנדו או ג'אנגו)
re היא ספריה סטנדרטית של פייתון שנותנת לנו יכולות טובות להפעיל regular expressions (או בקיצור regex - רגקס). כאשר יש מספר שיטות לשימוש ב-re. (מי שלא בקיא ברגקסים יכול להתחיל ללמוד באתר פרל בעברית http://perl.eitan.ac.il/main.php?id=00106)
search ו-match
search ו-match הן הפונקציות הבסיסיות של ביטויים רגולריים, הן מקבלות שני ערכים, הראשון הוא התבנית (pattern) והשני הוא המחרוזת (subject). ערכים נוספים שאפשר לשלוח הם נקודת התחלה, נקודת סיום ומודיפקטורים (modifiers).
במידה והתבנית מתאימה למחרוזת יחזור אובייקט מסוג re.MatchObject עליו נרחיב עוד מעט, אם לא יחזור לנו None.
ההבדלים בין search ל-match מסתכמים ב:
- search עובר על כל המחרוזת עד שהוא מוצא התאמה (או לא), match מחפש את התבנית בתחילת המחרוזת (במידה ונתנו נקודת התחלה שונה, הוא יחפש ממנה כמובן)
- ההתייחסות לשורה חדשה במצב של ריבוי שורות (מודיפקטור re.M) שונה, search מתייחס לכל שורה חדשה כהתחלה (עבור התו המיוחד ^) ואילו match מתייחס רק לתחילת המחרוזת:
>>> re.match('X', 'A\nB\nX', re.MULTILINE) # No match
>>> m = re.search('^X', 'A\nB\nX', re.MULTILINE) # Match
>>> m.start()
4
>>> m.end()
5
האובייקט המוחזר הוא מסוג re.MatchObject, המתודות המעניינות שלו הן group() שמחזירה מחרוזות שמורות (אוגרים) ומקבלת את המזהה של האוגר (החל מ-1), אם מצויין אוגר 0, יוחזר ההתאמה המלאה (ללא התייחסות לאוגרים), ואם ינתנו מספר פרמטרים כל הערכים המתאימים יחזרו כ-Tuple. פנייה לאוגר שלא קיים יזרוק חריגה IndexError: no such group
המתודה groups() מחזירה את כל האוגרים כ-Tuple, ומקבלת מחרוזת כפרמטר שיהיה ערך ברירת המחדל עבור אוגרים שאין להם תוכן (לא מחרוזות ריקות)
>>> m = re.match(r"(\d+)\.?(\d+)?", "24")
>>> m.groups() # Second group defaults to None.
('24', None)
>>> m.groups('0') # Now, the second group defaults to '0'.
('24', '0')
המתודה groupdict מחזירה את האוגרים שיש להם שם ייחוס כמילון (ומתעלמת מאלו שאין להם). כדי לתת שם ייחוס משתמשים במבנה: סימן שאלה, P גדולה ושם הייחוס מוקף בסוגריים משולשים, לדוגמא:
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+), (?P<profession>\w+)", "Albert Einstein, Physicist")
>>> m.groupdict()
{'first_name': 'Albert', 'last_name': 'Einstein', 'profession': 'Physicist'}
המתודות start ו-end מביאות את המיקום של ההתחלה והסוף של האוגר שניתן כפרמטר, אם לא צויין אוגר תחזור התוצאה המתאימה להתאמה המלאה (כמו במקרה של group(0))
>>> m.start()
0
>>> m.end()
26
>>> m.start(1)
0
>>> m.start(2)
7
>>> m.start(3)
17
>>> m.end(1)
6
>>> m.end(2)
15
>>> m.end(3)
26
קוד לדוגמא:
mad_dr@ubuntu:~$ cat url_parser.py
import re, sys, pprint
def parser(match):
if match is None:
print(" String doesn't match pattern")
return
template = ' group({}): {}'
for i in range(10):
try:
print(template.format(i, match.group(i)))
except IndexError:
if i < 3:
print(template.format(i, 'None'))
else:
break
pprint.pprint(match.groupdict('hostname'))
def main():
str = sys.argv[1]
print(str)
pattern = r'(?P\w+)://(?P[^\s/]+)/(?P[^\s#?]+)#?(?P[^\s?]+)?\??(?P\S+)?'
m = re.match(pattern, str)
parser(m)
return 0
if __name__ == '__main__':
ret_code = main()
sys.exit(ret_code)
mad_dr@ubuntu:~$
mad_dr@ubuntu:~$
mad_dr@ubuntu:~$ python3 url_parser.py 'https://docs.python.org/3/library/re.html#re.sub'
https://docs.python.org/3/library/re.html#re.sub
group(0): https://docs.python.org/3/library/re.html#re.sub
group(1): https
group(2): docs.python.org
group(3): 3/library/re.html
group(4): re.sub
group(5): None
{'headline': 're.sub',
'hostname': 'docs.python.org',
'parameters': 'hostname',
'path': '3/library/re.html',
'protocol': 'https'}
וכמו שאתם רואים, יש באג עם אוגרים ריקים... אם למישהו יש הסבר הוא מוזמן לשתף בתגובות. תיעוד - [1]