ביטויים רגולריים של לינוקס. חמש דוגמאות לשימוש ב-grep Egrep ביטוי רגולרי דוגמאות

06.12.2021

על הדרכה זו

ברוכים הבאים ל- Basics of Administration, המדריכים השני מתוך ארבעת שנועדו להכין אותך לבחינה 101 ב-Linux Professional Institute. בחלק זה, נבחן כיצד להשתמש בביטויים רגולריים כדי לחפש טקסט בקבצים המבוססים על דפוסים. לאחר מכן, תכירו את "תקן ההיררכיה של מערכת הקבצים" (תקן היררכיה של מערכת הקבצים או בקיצור FHS), וגם נראה לכם כיצד למצוא את הקבצים הדרושים לכם במערכת שלכם. לאחר מכן, תלמדו כיצד לקחת שליטה מלאה על תהליכי לינוקס על ידי הפעלתם ברקע, פירוט תהליכים, ניתוקם מהמסוף ועוד. להלן מבוא מהיר לצינורות, הפניות מחדש ופקודות עיבוד טקסט. לבסוף, נציג בפניכם את מודולי ליבת לינוקס.

בפרט, חלק זה של המדריך (חלק 2) הוא אידיאלי עבור אלה שכבר יש להם ידע בסיסי טוב ב-bash ורוצים היכרות טובה עם משימות ניהול בסיסיות של לינוקס. אם אתה חדש בלינוקס, אנו ממליצים לך להשלים תחילה את החלק הראשון של סדרת ההדרכה הזו. עבור חלקם, רוב החומר הזה יהיה חדש, אבל משתמשי לינוקס מנוסים יותר עשויים למצוא זאת דרך מצוינת לסכם את כישורי הניהול הבסיסיים שלהם.



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

ביטויים רגולריים

מהו "ביטוי רגולרי"?

ביטוי רגולרי (לפי ביטוי רגולרי באנגלית, ראשי תיבות "regexp" או "regex", במולדת נקרא לפעמים "רגיל" - בערך ליין) הוא תחביר מיוחד המשמש לתיאור תבניות טקסט. במערכות לינוקס, ביטויים רגולריים נמצאים בשימוש נרחב עבור התאמת דפוסים בטקסט, ולפעולות חיפוש והחלפה בזרמי טקסט.

בהשוואה לגלובינג

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

מחרוזת משנה פשוטה

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

$ grep bash /etc/passwd
operator:x:11:0:operator:/root:/bin/bash root:x:0:0::/root:/bin/bash ftp:x:40:1::/home/ftp:/bin/ לַחֲבוֹט

למעלה, הפרמטר הראשון ל-grep הוא regex; השני הוא שם הקובץ. grep קרא כל שורה מ / etc / passwdוהחילו עליו תת-מחרוזת "bash" פשוטה בחיפוש אחר התאמה. אם נמצאה התאמה, אז grep הדפיס את כל השורה; אחרת, השורה התעלמה.

הבנת מחרוזת משנה פשוטה

באופן כללי, אם אתה מחפש מחרוזת משנה, אתה יכול פשוט לציין אותה מילולית, מבלי להשתמש בתווים "מיוחדים". אתה רק צריך להיזהר במיוחד אם המחרוזת המשנה שלך מכילה +, ., *, [, ] או \, ובמקרה זה יש לחלף את התווים הללו עם קווים אחוריים ואת המחרוזת מוקפת במירכאות. להלן כמה דוגמאות לביטויים רגולריים כמחרוזת משנה פשוטה:

  • /tmp (חפש את שורת /tmp)
  • "\" (חיפוש מחרוזת)
  • "\*מצחיק\*" (חפש מחרוזת *מצחיק*)
  • "ld\.so" (חפש מחרוזת ld.so)

מטא-תווים

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

$ grep dev.sda /etc/fstab
/dev/sda3 / reiserfs noatime,ro 1 1 /dev/sda1 /boot reiserfs noauto,noatime,notail 1 2 /dev/sda2 swap swap sw 0 0 #/dev/sda4 /mnt/extra reiserfs noatime,rw 1 1

בדוגמה זו, הטקסט dev.sda לא מופיע ממש באף אחת מהשורות ב /etc/fstab. עם זאת, grep לא ממש סורק אותו עבור קו dev.sda, אלא עבור דפוס dev.sda. זכור את זה "." יתאים לכל תו בודד. כפי שאתה יכול לראות, ה-"." הוא שווה ערך מבחינה תפקודית לאופן שבו פועל המטא "?". בהחלפות גלוב.

נוֹהָג

אם ברצוננו לציין תו באופן ספציפי יותר ממה ש-"." עושה, נוכל להשתמש ב-[ ו-] (סוגריים מרובעים) כדי לציין קבוצת משנה של תווים שתתאים:

$ grep dev.sda /etc/fstab
/dev/sda1 /boot reiserfs noauto,noatime,notail 1 2 /dev/sda2 swap swap sw 0 0

כפי שאתה יכול לראות, במיוחד, המבנה התחבירי הזה עובד באופן זהה למבנה "" בהחלפת שם הקובץ של glob. שוב, זו אחת העמימות בלמידת ביטויים רגולריים: התחביר דומה, אך לא זהה, להחלפות גלוב, וזה מבלבל.

שימוש ב-[^]

אתה יכול להפוך את המשמעות של סוגריים מרובעים על ידי הצבת ^ מיד אחרי ה-[. במקרה זה, הסוגריים יתאימו לכל תו שלא רשום בתוכם. שוב, שימו לב שאנו משתמשים ב-[^] עם regex ו-[!] עם glob:

$ grep dev.hda[^12] /etc/fstab
/dev/hda3 / reiserfs noatime,ro 1 1 #/dev/hda4 /mnt/extra reiserfs noatime,rw 1 1

תחביר שונה

חשוב מאוד לציין שהתחביר בתוך סוגריים מרובעים שונה מהותית משאר הביטוי הרגולרי. לדוגמה, אם תכניס "." בתוך הסוגריים המרובעים, זה יאפשר לסוגריים המרובעים להתאים את "." פשוטו כמשמעו, בדיוק כמו 1 ו-2 בדוגמה למעלה. לצורך השוואה, "." הממוקם מחוץ לסוגריים מרובעים יתפרש כתו מטא אלא אם יש "\" בקידומת. אנו יכולים לנצל עובדה זו כדי להדפיס שורות מ-/etc/fstab המכילות את השורה dev.sda כפי שנכתב:

$ grep dev[.]sda /etc/fstab

כמו כן, נוכל להקליד:

$ grep "dev\.sda" /etc/fstab

הביטויים הרגולריים האלה כנראה לא תואמים לאף אחת מהשורות שלך. /etc/fstabקוֹבֶץ.

סמל מתמטיקה *

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

  • א ב גמתאים ל-"abbbbc" אבל לא "abqc" (במקרה של החלפת גלוב, שתי המחרוזות יתאימו לתבנית. אתה מבין למה?)
  • א ב גמתאים ל-"abc" אבל לא "abbqbbc" (שוב, עם החלפת גלוב, התבנית תואמת את שתי המחרוזות)
  • א ב גמתאים ל-"ac" אבל לא "cba" (במקרה של גלוב, לא "ac" ולא "cba" תואמים את התבנית)
  • לִהיוֹתתואם "bqe" ו-"be" (החלפה גלובלית תואמת "bqe" אך לא "be")
  • לִהיוֹתמתאים ל-"bccqqe" אך לא ל-"bccc" (בעת גלוב, התבנית תתאים גם לראשון, אך לא לשני)
  • לִהיוֹתמתאים ל-"bqqcce" אך לא "cqe" (אותו הדבר עם החלפת גלוב)
  • לִהיוֹתמספק את "בבי" (אבל לא במקרה של גלוב)
  • .* מתאים לכל מחרוזת (החלפת גלוב תואמת רק מחרוזות שמתחילות ב-".")
  • פו.*יתאים לכל מחרוזת משנה שמתחילה ב-"foo" (במקרה של החלפת גלוב, תבנית זו תתאים למחרוזות שמתחילות בארבעת התווים "foo").

לכן, לסיכום, המחרוזת "ac" תואמת את הביטוי הרגולרי "ab*c" מכיוון שהכוכבית מאפשרת גם לחזור על הביטוי הקודם (b) אפס פעמים. ושוב, כדאי לשים לב בעצמכם שהתו המטא * בביטויים רגולריים מתפרש אחרת לגמרי מהתו * בהחלפות גלוב.

התחלה וסוף שורה

המטא-תווים האחרונים שנסתכל עליהם בפירוט הם ^ ו-$, המשמשים להתאמת ההתחלה והסוף של מחרוזת, בהתאמה. על ידי שימוש ב-^ בתחילת הביטוי הרגולרי שלך, אתה "מצרף" את התבנית שלך לתחילת השורה. בדוגמה הבאה, אנו משתמשים בביטוי הרגולרי ^#, התואם לכל מחרוזת שמתחילה בתו #:

$ grep ^# /etc/fstab

#

ביטויים רגולריים בקו מלא

ניתן לשלב ^ ו-$ כדי להתאים לכל המחרוזת. לדוגמה, הביטוי הרגולרי הבא יתאים למחרוזות שמתחילות ב-# ומסתיימות ב-".", עם מספר שרירותי של תווים ביניהן:

$ grep "^#.*\.$" /etc/fstab
# /etc/fstab: מידע סטטי על מערכת הקבצים.

בדוגמה שלמעלה, צירפנו את הביטוי הרגולרי שלנו במירכאות בודדות כדי למנוע מהתו $ להתפרש על ידי המעטפת. ללא המירכאות הבודדות, $ היה נעלם מהביטוי הרגולרי שלנו לפני ש-grep יכול היה לראות אותו.

על המחברים

דניאל רובינס

דניאל רובינס הוא המייסד של קהילת ג'נטו והיוצר של מערכת ההפעלה ג'נטו לינוקס. דניאל מתגורר בניו מקסיקו עם אשתו מרי ושתי בנות נמרצות. הוא גם המייסד והראש של Funtoo, וכתב מאמרים טכניים רבים עבור IBM developerWorks, Intel Developer Services ו-C/C++ Users Journal.

כריס האוזר

כריס האוזר הוא תומך UNIX מאז 1994, כאשר הצטרף לצוות הניהול באוניברסיטת טיילור, אינדיאנה, ארה"ב, שם קיבל תואר ראשון במדעי המחשב ומתמטיקה. מאז הוא עבד במגוון תחומים כולל יישומי אינטרנט, עריכת וידאו, מנהלי התקנים של UNIX ואבטחה קריפטוגרפית. עובד כיום ב- Sentry Data Systems. כריס גם תרם לפרויקטים רבים של קוד פתוח כמו Gentoo Linux ו- Clojure והיה שותף בכתיבת The Joy of Clojure.

ארון גריפיס

איירון גריפיס מתגורר באזור בוסטון, שם בילה את העשור האחרון בעבודה עבור Hewlett-Packard בפרויקטים כגון מנהלי התקנים של רשת UNIX עבור Tru64, הסמכת אבטחה לינוקס, וירטואליזציה של Xen ו-KVM, ולאחרונה פלטפורמת HP ePrint. בזמנו הפנוי מתכנות, אהרון מעדיף להרהר בבעיות התכנות בזמן שהוא רוכב על אופניו, מלהטט באלות או מעודד את קבוצת הבייסבול המקצועית של בוסטון רד סוקס.

בשעה טובה, אורחים!

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

מלכתחילה, ישנם מספר סוגים של ביטויים רגולריים:

1. ביטויים רגולריים מסורתיים(הם בסיסיים, בסיסיים ו ביטויים רגולריים בסיסיים(BRE))

  • התחביר של ביטויים אלה מוגדר כמוצאה משימוש, אך עם זאת הוא עדיין בשימוש נרחב ונמצא בשימוש על ידי כלי עזר רבים של UNIX
  • ביטויים רגולריים בסיסיים כוללים את המטא-תווים הבאים (עוד על משמעויותיהם בהמשך):
    • \(\) - מקורי עבור ( ) (מורחב)
    • \(\) - מקורי עבור () (מורחב)
    • \נ, איפה נ- מספר מ-1 עד 9
  • תכונות השימוש במטא-תווים אלה:
    • הכוכבית חייבת לבוא אחרי הביטוי התואם לתו הבודד. דוגמא: *.
    • ביטוי \( לַחסוֹם\)* צריך להיחשב בלתי חוקי. במקרים מסוימים, הוא תואם אפס חזרות או יותר של מחרוזת לַחסוֹם. באחרים זה תואם את המיתר לַחסוֹם* .
    • בתוך מחלקת תווים, בדרך כלל מתעלמים מערכי תווים מיוחדים. מקרים מיוחדים:
    • כדי להוסיף תו ^ לקבוצה, אסור למקם אותו שם קודם.
    • כדי להוסיף דמות - לסט, יש למקם אותה במקום הראשון או אחרון. לדוגמה:
      • תבנית שם DNS, שיכולה לכלול אותיות, מספרים, מינוס ונקודה מפריד: [-0-9a-zA-Z.] ;
      • כל תו מלבד מינוס וספרה: [^-0-9] .
    • כדי להוסיף תו [ או ] לקבוצה, יש למקם אותו שם תחילה. לדוגמה:
      • תואם ] , [ , a או b .

2. ביטויים רגולריים מורחבים(הם ביטויים רגולריים מורחבים(ERE))

  • התחביר של ביטויים אלה דומה לתחביר של ביטויים בסיסיים, למעט:
    • הוסר את השימוש באלכסונים אחוריים עבור תווים מטא () ו-().
    • קו נטוי לפני תו מטא מבטל את המשמעות המיוחדת שלו.
    • נדחה תיאורטית לֹא סָדִירבנייה \ נ .
    • נוספו תווים מטא + , ? , | .

3. ביטויים רגולריים תואמי Perl(הם ביטויים רגולריים תואמי Perl(PCRE))

  • יש תחביר עשיר אך צפוי יותר אפילו מה-POSIX ERE, ולכן הם משמשים לעתים קרובות על ידי יישומים.

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

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

ספירה |

פס אנכי (|)מפריד בין האפשרויות התקפות, אנו יכולים לומר - OR לוגי. לדוגמה, התאמות "אפור|אפור". אפוראוֹ אפור.

קיבוץ או איחוד()

סוגריים עגוליםמשמשים לקביעת ההיקף והקדימות של אופרטורים. לדוגמה, "אפור|אפור" ו-"gr(a|e)y" הם דפוסים שונים, אך שניהם מתארים קבוצה המכילה אפורו אפור.

Quantify() ? * +

מכמתלאחר שדמות או קבוצה קובעים כמה פעמים קוֹדֵםביטוי עשוי להתרחש.

ביטוי כללי, חזרות יכולות להיות מ-m ועד n כולל.

ביטוי כללי, מ' או יותר חזרות.

ביטוי כללי, לא יותר מ-n חזרות.

חלקn חזרות.

סימן שאלהאומר 0 או 1פעמים, אותו דבר כמו {0,1} . לדוגמה, "colour?r" תואם ו צֶבַע, ו צֶבַע.

כוכבאומר 0, 1 או כל מספרפעם אחת ( {0,} ). לדוגמה, תואם "go*gle". לגלג, גוגל, גוגלוכו.

יתרוןאומר לפחות 1פעם אחת ( {1,} ). לדוגמה, "גו+גל" מתאים גוגל, גוגלוכו' (אבל לא לגלג).

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

מטא-תווים, במילים פשוטות, אלו סמלים שאינם תואמים את המשמעות האמיתית שלהם, כלומר סמל. (נקודה) אינה נקודה, אלא כל תו אחד וכו'. אני מבקש ממך להכיר את המטא-תווים ומשמעויותיהם:

. מתאים ל לבדכל דמות
[משהו] מתכתב כל אדםתו מבין אלה המוקפים בסוגריים. במקרה זה: התו "-" מתפרש כפשוטו רק אם הוא ממוקם מיד לאחר הפתיחה או לפני הסוגריים הסוגרים: או [-abc]. אחרת, הוא מציין מרווח תווים. לדוגמה, מתאים ל-"a", "b" או "c". מתאים לאותיות באותיות קטנות של האלפבית הלטיני. ניתן לשלב גם סימונים אלו: התאמות a, b, c, q, r, s, t, u, v, w, x, y, z. כדי להתאים את התווים "[" או "]", מספיק סוגר הסיום היה התו הראשון אחרי תו הפתיחה: מתאים ל"]", "[", "a" או "b". דמות בודדתמבין אלה שאינם בסוגריים. לדוגמה, [^abc] תואם לכל תו מלבד "a", "b" או "c". [^a-z] מתאים לכל תו מלבד אותיות קטנות באלפבית הלטיני.
^ מתאים לתחילת הטקסט (או לתחילת שורה כלשהי אם המצב הוא שורה אחר שורה).
$ מתאים לסוף הטקסט (או סוף שורה כלשהי אם המצב מוטבע).
\(\) או () מכריז על "תת-ביטוי מסומן" (ביטוי מקובץ) שניתן להשתמש בו מאוחר יותר (ראה האלמנט הבא: \ נ). "תת-ביטוי מסומן" הוא גם "חסימה". בניגוד לאופרטורים האחרים, זה (בתחביר המסורתי) דורש נטוי אחורי, ב-extended וב-Perl, אין צורך בתו \ -.
\נ איפה נהוא מספר מ-1 עד 9; מתאים ל נביטוי המשנה המסומן (למשל (abcd)\0, כלומר תווי abcd מסומנים באפס). עיצוב זה הוא תיאורטי לֹא סָדִיר, זה לא התקבל בתחביר ביטוי רגולרי מורחב.
*
  • כוכבלאחר ביטוי התואם תו בודד, תואם אֶפֶסאוֹ יותר עותקיםהביטוי (הקודם) הזה. לדוגמה, "*" מתאים למחרוזת הריקה, "x", "y", "zx", "zyx" וכו'.
  • \נ*, איפה נהוא ספרה מ-1 עד 9, תואם אפס מופעים או יותר כדי להתאים נביטוי משנה מסומן. לדוגמה, "\(a.\)c\1*" מתאים ל-"abcab" ו-"abcaba" אך לא ל-"abcac".

ביטוי המוקף ב-"\(" ו-"\)" ואחריו "*" צריך להיחשב לא חוקי. במקרים מסוימים, הוא תואם לאפס מופעים או יותר של המחרוזת בסוגריים. באחרים, הוא תואם את הביטוי בסוגריים, בהינתן התו "*".

\{איקס,y\} מתאים לאחרון ( הקרוב) לחסימה שמתרחשת לפחות איקסולא יותר yפַּעַם. לדוגמה, "a\(3,5\)" תואם ל-"aaa", "aaaa" או "aaaaa". בניגוד לאופרטורים האחרים, זה (בתחביר המסורתי) דורש נטוי אחורי.
.* ציון מספר כלשהו של תווים בין שני חלקים של ביטוי רגולרי.

תווים מטא עוזרים לנו להשתמש בהתכתבויות שונות. אבל איך אפשר לייצג תו רגיל על ידי תו רגיל, כלומר התו [ (סוגריים מרובעים) בערך של סוגר מרובע? רַק:

  • חייב להיות ראשוני מָגֵן) מטא-תו (. * + \ ? ( )) ואחריו נטוי אחורי. לדוגמה \. או \[

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

שיעור POSIX כְּמוֹ כֵן יִעוּד
[:עֶלִיוֹן:] אותיות רישיות
[:נמוך יותר:] אותיות קטנות
[:alpha:] אותיות רישיות ואותיות קטנות
[:alnum:] מספרים, אותיות רישיות וקטנות
[:סִפְרָה:] מספרים
[:xdigit:] ספרות הקסדצימליות
[:נְקוּדָה:] [.,!?:…] סימני פיסוק
[:רֵיק:] [\t] חלל ו-TAB
[:מֶרחָב:] [\t\n\r\f\v] לדלג על תווים
[:cntrl:] סמלי שליטה
[:גרָף:] [^ \t\n\r\f\v] סמלי חותם
[:הדפס:] [^\t\n\r\f\v] להדפיס תווים ולדלג על תווים

ב-regex יש דבר כזה:

רגקס של חמדנות

אנסה לתאר בצורה הכי ברורה שאפשר. נניח שאנו רוצים למצוא את כל תגי ה-HTML בטקסט כלשהו. לאחר שהתייחסנו לבעיה, אנו רוצים למצוא את הערכים שביניהם< и >, יחד עם הסוגריים האלה. אבל אנחנו יודעים שלתגים יש אורכים שונים ויש לפחות 50 תגיות בעצמם. לרשום את כולם, לכלול אותם בתווים מטא, זו משימה קשה מדי. אבל אנחנו יודעים שיש לנו ביטוי.* (נקודה כוכבית) המאפיין כל מספר של תווים כלשהם במחרוזת. באמצעות ביטוי זה, ננסה למצוא בטקסט (

לכן, כיצד ליצור RAID רמה 10/50 בבקר LSI MegaRAID (רלוונטי גם עבור: Intel SRCU42x, Intel SRCS16):

) כל הערכים בין< и >. כתוצאה מכך, המחרוזת כולה תתאים לביטוי זה. למה, כי הביטוי הרגולרי הוא חמדן ומנסה ללכוד את כל מספר התווים שביניהם< и >, בהתאמה, כל הקו, מתחיל < p> אז...וסיום ...> יהיה שייך לכלל זה!

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

  • לשקול סמלים, לֹאהתאמה לתבנית הרצויה (לדוגמה:<[^>]*> למקרה שלמעלה)
  • להיפטר מתאוות בצע על ידי הוספת הגדרת כימת כלא חמדנית:
    • *? - "לא חמדן" ("עצלן") שווה ערך *
    • +? - "לא חמדן" ("עצלן") שווה ערך +
    • (נ)? - "לא חמדן" ("עצלן") מקבילה של (n,)
    • .*? - שווה ערך "לא חמדן" ("עצלן").*

אני רוצה להוסיף את כל האמור לעיל. תחביר ביטוי רגולרי מורחב:

ביטויים רגולריים ב-POSIX דומים לתחביר ה-Unix המסורתי, אך עם תוספת של כמה תווים מטא:

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

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

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

השימוש באותיות אחוריות הוצא משימוש: \(…\) הופך ל-(...) ו-\(...\) הופך ל-(...).

בסוף הפוסט, הנה כמה דוגמאות לשימוש רגיל:

$ חתול טקסט1 1 תפוח 2 אגס 3 בננה $ grep p text1 1 תפוח 2 אגס $ grep "pp*" text1 1 תפוח 2 אגס $ חתול טקסט1 | grep "l\|n" 1 apple 3 banana $ echo -e "מצא\n* כאן" | grep "\*" * כאן $ grep "pl\?.*r" text1 # p, על שורות עם r 2 אגס $ grep "a.." text1 # שורות עם a ואחריו לפחות 2 תווים 1 תפוח 3 בננה $ grep "" text1 # חפש שורות המכילות 3 או p 1 תפוח 2 אגס 3 בננה $ echo -e "מצא\n* כאן\nאיפשהו." | grep "[.*]" * כאן איפשהו..שם]$ echo -e "123\n456\n789\n0" | grep "" 123 456 789 $ sed -e "/\(a.*a\)\|\(p.*p\)/s/a/A/g" text1 # החלף a ב-A בכל השורות כאשר לאחר מכן a מגיע a או אחרי p בא p 1 תפוח 2 אגס 3 bAnAnA *\./ מילה אחרונה./ג" ראשית. מילה אחרונה. זו מילה אחרונה.

בכבוד רב, מק.סים!

כלי השירות grep הוא כלי רב עוצמה לאיתור וסינון מידע טקסט. מאמר זה מציג מספר דוגמאות לשימוש בו, שיאפשרו לך להעריך את היכולות שלו.
השימוש העיקרי ב-grep הוא חיפוש מילים או ביטויים בקבצים ובזרמי פלט. אתה יכול לחפש על ידי הקלדת שאילתה ואזור חיפוש (קובץ) בשורת הפקודה.
לדוגמה, כדי למצוא את המחרוזת "needle" בקובץ hystack.txt, השתמש בפקודה הבאה:

$ grep needle haystack.txt

כתוצאה מכך, grep יציג את כל המופעים של מחט שהוא נתקל בתוכן הקובץ haystack.txt. חשוב לציין שבמקרה זה, grep מחפש קבוצה של תווים, לא מילה. לדוגמה, יוצגו שורות המכילות את המילה "מיותר" ומילים אחרות המכילות את הרצף "מחט".


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

$ grep -w needle haystack.txt

אין צורך להגביל את החיפוש לקובץ אחד בלבד, grep יכול גם לחפש בקבוצת קבצים, ותוצאות החיפוש יפרטו את הקובץ המתאים. המתג -n יוסיף גם את מספר השורה בה נמצאה התאמה, והבורר -r יאפשר לך לבצע חיפוש רקורסיבי. זה מאוד שימושי בעת חיפוש בין קבצים עם טקסטים של מקור תוכנה.

$ grep -rnw function_name /home/www/dev/myprogram/

שם הקובץ יופיע לפני כל התאמה. אם אתה צריך להסתיר שמות קבצים, השתמש במתג -h, להיפך, אם יש צורך בשמות קבצים בלבד, ציין את המתג -l
בדוגמה הבאה, נחפש כתובות URL בקובץ יומן IRC ונראה את 10 ההתאמות האחרונות.

$ grep -wo http://.* channel.log | זָנָב

האפשרות -o אומרת ל-grep להוציא רק את התאמת הדפוס, לא את כל השורה. פלט grep מועבר לפקודה זנב, שמדפיסה את 10 השורות האחרונות כברירת מחדל.
כעת נספור את מספר ההודעות שנשלחו לערוץ irc על ידי משתמשים מסוימים. למשל, כל ההודעות ששלחתי מהבית ומהעבודה. הם שונים בכינוי, בבית אני משתמש בכינוי משתמש_בבית, ובעבודה, משתמש_בעבודה.

$ grep -c "^user_at_(home|work)" channel.log

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

$ grep -w "+(5,)" channel.log

לתיאור מפורט יותר, עיין בדף האיש של grep.
עוד כמה דוגמאות:

# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin

מציג שורות מהקובץ /etc/passwd המכילות את שורש המחרוזת.

# grep -n root /etc/passwd 1:root:x:0:0:root:/root:/bin/bash 12:operator:x:11:0:operator:/root:/sbin/nologin

בנוסף, מוצגים מספרי השורות המכילים את מחרוזת החיפוש.

# grep -v bash /etc/passwd | grep -v nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin :/sbin/halt news:x:9:13:news:/var/spool/news: mailnull:x:47:47::/var/spool/mqueue:/dev/null xfs:x:43:43: X Font Server:/etc/X11/fs:/bin/false rpc:x:32:32:Portmapper RPC user:/:/bin/false nscd:x:28:28:NSCD Daemon:/:/bin/false named:x:25:25:Named:/var/named:/bin/false squid:x:23:23::/var/spool/squid:/dev/null ldap:x:55:55:LDAP משתמש: /var/lib/ldap:/bin/false apache:x:48:48:Apache:/var/www:/bin/false

בודק אילו משתמשים אינם משתמשים ב-bash, למעט חשבונות המשתמשים שיש להם nologin כקליפה.

# grep -c false /etc/passwd 7

סופר את מספר החשבונות שיש להם /bin/false כקליפה.

# grep -i games ~/.bash* | היסטוריית grep -v

פקודה זו מפרטת שורות מכל הקבצים בספריית הבית של המשתמש הנוכחי שמתחילות ב-~/.bash, למעט אותם קבצים שיש להם את היסטוריית המחרוזות בשמותיהם, כדי לא לכלול את ההתאמות שנמצאו בקובץ ~/.bash_history שבו יכול להיות אותה מחרוזת באותיות גדולות או קטנות. שים לב שהחיפוש אחר המילה "משחקים" מתבצע, אתה יכול להחליף כל אחר במקום.
פקודת grep וביטויים רגולריים

בשונה מהדוגמה הקודמת, כעת נציג רק את השורות שמתחילות במחרוזת "שורש":

# grep ^root /etc/passwd root:x:0:0:root:/root:/bin/bash

אם אנו רוצים לראות אילו חשבונות כלל לא השתמשו במעטפת, נחפש שורות המסתיימות ב-":":

# grep:$ /etc/passwd news:x:9:13:news:/var/spool/news:

כדי לבדוק אם המשתנה PATH בקובץ ~/.bashrc מיוצא, תחילה בחר את השורות עם "ייצוא" ולאחר מכן חפש שורות שמתחילות במחרוזת "PATH"; במקרה זה MANPATH ונתיבים אפשריים אחרים לא יוצגו:

# grep export ~/.bashrc | grep "PATH" export PATH="/bin:/usr/lib/mh:/lib:/usr/bin:/usr/local/bin:/usr/ucb:/usr/dbin:$PATH"

שיעורי אופי

ביטוי בסוגריים מרובעים הוא רשימה של תווים המוקפים בתוך התווים [" ו"]"". זה מתאים לכל תו בודד ברשימה זו; אם התו הראשון ברשימה הוא "^", אז הוא מתאים לכל תו שאינו קיים ברשימה. לדוגמה, הביטוי הרגולרי "" מתאים לכל ספרה בודדת.

בתוך ביטוי בסוגריים מרובעים, ניתן לציין טווח המורכב משני תווים מופרדים במקף. ואז הביטוי מתאים לכל תו בודד שעל פי כללי המיון, נכנס לשתי התווים הללו, כולל שתי התווים הללו; זה לוקח בחשבון את רצף האיסוף וערכת התווים שצוינו במקום. לדוגמה, כאשר מקום ברירת המחדל הוא C, הביטוי "" שווה ערך לביטוי "". ישנם אזורים רבים שבהם המיון נעשה לפי סדר מילון, ובמקומות אלו "" אינו שווה ערך בדרך כלל ל"", בהם, למשל, הוא יכול להיות שווה ערך לביטוי "". כדי להשתמש בפירוש המסורתי של הביטוי בסוגריים, אתה יכול להשתמש במיקום C על ידי הגדרת משתנה הסביבה LC_ALL ל-"C".

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

# grep /etc/group sys:x:3:root,bin,adm tty:x:5: mail:x:12:mail,postfix ftp:x:50: nobody:x:99: floppy:x:19: xfs:x:43: nfsnobody:x:65534: postfix:x:89:

הדוגמה מציגה את כל השורות המכילות את התו "y" או את התו "f".
תווים כלליים (תווים מטא-תווים)

להשתמש "." כדי להתאים לכל דמות בודדת. אם ברצונך לקבל רשימה של כל המילים באנגלית שנלקחו ממילון המכיל חמש תווים שמתחילים ב-"c" ומסתיימים ב-"h" (שימושי לפתרון תשבצים):

# grep " " /usr/share/dict/words catch clash בד מאמן ספה שיעול התרסקות ריסוק

אם ברצונך להציג שורות המכילות תו נקודה בתור מילולי, השתמש באפשרות -F עם הפקודה grep. סמלים"< " и «>» פירושה נוכחות של מחרוזת ריקה לפני ובהתאמה, אחרי האותיות שצוינו. המשמעות היא שהמילים בקובץ המילים חייבות להיות כתובות כראוי. אם ברצונך למצוא את כל המילים בטקסט עבור התבניות שצוינו, למעט שורות ריקות, השמט את התווים "< " и «>", לחיפוש מדויק יותר של מילים בלבד, השתמש במתג -w.

כדי לחפש באופן דומה מילים שיכולות להכיל כל מספר של תווים בין "c" ל- "h", השתמש בכוכבית (*). הדוגמה הבאה בוחרת את כל המילים שמתחילות ב-"c" ומסתיימות ב-"h" מתוך מילון המערכת:

# grep " " /usr/share/dict/words ח'ליף מזומן לתפוס צ'יטה מבד גבינה --פלט הושמט--

אם אתה רוצה לחפש תו כוכבית מילולי בקובץ או בזרם פלט, השתמש במירכאות בודדות כדי לעשות זאת. המשתמש בדוגמה למטה מנסה תחילה למצוא את ה"כוכבית" בקובץ /etc/profile מבלי להשתמש במירכאות, מה שלא גורם לשום דבר. כאשר משתמשים במרכאות, התוצאה מודפסת לזרם הפלט:

# grep * /etc/profile # grep "*" /etc/profile for i ב-/etc/profile.d/*.sh ; לַעֲשׂוֹת

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

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

מהם ביטויים רגולריים

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


לדעתנו, אפילו מתחיל מוחלט יבין מיד איך זה עובד ולמה אתה צריך את זה :) אם אתה לא כל כך מבין, פשוט המשך לקרוא והכל יסתדר.
ביטוי רגולרי הוא דפוס שתוכנות כמו sed או awk משתמשות בו כדי לסנן טקסט. תבניות משתמשות בתווי ASCII רגילים המייצגים את עצמם, ובמה שנקרא מטא-תווים, אשר ממלאים תפקיד מיוחד, למשל, המאפשרים לך להתייחס לקבוצות מסוימות של תווים.

סוגי ביטוי רגולרי

למימוש ביטוי רגולרי בסביבות שונות, כמו שפות תכנות כמו Java, Perl ו-Python, וכלי לינוקס כמו sed, awk ו-grep, יש מוזרויות מסוימות. תכונות אלו תלויות במה שנקרא מנועי regex שמפרשים דפוסים.
ישנם שני מנועי ביטוי רגולרי בלינוקס:
  • מנוע התומך בתקן POSIX Basic Regular Expression (BRE).
  • מנוע התומך בתקן POSIX Extended Regular Expression (ERE).
רוב כלי השירות של לינוקס תואמים לפחות את תקן POSIX BRE, אבל חלק מהכלים (כולל sed) מבינים רק תת-קבוצה של תקן BRE. אחת הסיבות למגבלה זו היא הרצון להפוך כלי עזר כאלה מהר ככל האפשר בעיבוד תמלילים.

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

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

ביטויים רגולריים של POSIX BRE

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

$ echo "זהו מבחן" | sed -n "/ test / p" $ echo "זהו מבחן" | awk "/ test / (הדפס $ 0)"

מחפש טקסט לפי דפוס ב-sed


מציאת טקסט לפי דפוס ב-awk

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

כשאתה עובד עם ביטויים רגולריים, זכור שהם תלויי רישיות:

$ echo "זהו מבחן" | awk "/ מבחן / (הדפס $ 0)" $ echo "זהו מבחן" | awk "/ test / (הדפס $ 0)"

ביטויים רגולריים הם תלויי רישיות

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

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

$ echo "זה שוב מבחן 2" | awk "/ בדיקה 2 / (הדפס $ 0)"

מצא פיסת טקסט המכילה רווחים ומספרים

מנוע הרקס מתייחס לרווחים כאל תווים רגילים.

סמלים מיוחדים

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

.*^${}\+?|()
אם יש צורך באחד מהם בתבנית, יהיה צורך להמלט ממנו באמצעות קו נטוי אחורי (לאחור) - \.

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

יש 10 $ על הכיס שלי
ניתן לזהות את סימן הדולר באמצעות דפוס כזה:

$ awk "/ \ $ / (הדפס $ 0)" שלי

שימוש בתו מיוחד בתבנית

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

$ echo "\ הוא תו מיוחד" | awk "/ \\ / (הדפס $ 0)"

קו נטוי אחורי בורח

למרות שהלוכסן קדימה אינו כלול ברשימת התווים המיוחדים לעיל, ניסיון להשתמש בו בביטוי רגולרי שנכתב עבור sed או awk יגרום לשגיאה:

$ echo "3/2" | awk "/// (הדפס $ 0)"

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

אם אתה צריך את זה, אתה צריך גם לסנן את זה:

$ echo "3/2" | awk "/ \ // (הדפס $ 0)"

נמלט קדימה סלאש

סמלי עוגן

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

$ echo "ברוכים הבאים לאתר likegeeks" | awk "/ ^ likegeeks / (הדפס $ 0)" $ echo "likegeeks website" | awk "/ ^ likegeeks / (הדפס $ 0)"

מציאת תבנית בתחילת שורה

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

$ awk "/ ^ זה / (הדפס $ 0)" הקובץ שלי


חפש דפוס בתחילת שורה בטקסט מקובץ

עם sed, אם תניח כובע בכל מקום בתוך התבנית, הוא יטופל כמו כל דמות רגילה אחרת:

$ echo "זה ^ זה מבחן" | sed -n "/ s ^ / p"

כיסוי לא בתחילת תבנית ב-sed

ב-awk, בעת שימוש באותה דפוס, יש לבצע בריחה מהתו הנתון:

$ echo "זה ^ זה מבחן" | awk "/ s \ ^ / (הדפס $ 0)"

כריכה לא בתחילת התבנית ב-awk

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

סימן הדולר - $, שהוא תו העוגן לסוף השורה, יעזור לנו בכך:

$ echo "זהו מבחן" | awk "/ test $ / (הדפס $ 0)"

מציאת טקסט בסוף שורה

ניתן להשתמש בשני תווי העוגן באותה תבנית. בואו נעבד את הקובץ myfile, שתוכנו מוצג באיור למטה, באמצעות הביטוי הרגולרי הבא:

$ awk "/ ^ זה מבחן $ / (הדפס $ 0)" הקובץ שלי


תבנית המשתמשת בתווים מיוחדים לתחילתה ולסופה של שורה

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

הנה איך לסנן שורות ריקות באמצעות תווי עוגן:

$ awk "! / ^ $ / (הדפס $ 0)" שלי
בתבנית זו השתמשתי בסמל השלילה, בסימן הקריאה -! . תבנית זו מחפשת שורות שאינן מכילות דבר בין ההתחלה לסוף השורה, וסימן הקריאה מדפיס רק קווים שאינם תואמים לתבנית.

סמל נקודה

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

$ awk "/.st/(הדפס $ 0)" שלי


שימוש בנקודה בביטויים רגולריים

כפי שניתן לראות מהנתונים המוצגים, רק שתי השורות הראשונות מהקובץ תואמות את התבנית, שכן הן מכילות את רצף התווים "st", שלפניו תו אחד נוסף, בעוד שהשורה השלישית אינה מכילה רצף מתאים, וכן ברביעי זה כן, אבל הוא ממש בתחילת השורה.

שיעורי אופי

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

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

$ awk "/ th / (הדפס $ 0)" שלי


תיאור מחלקה של תו ביטוי רגולרי

כאן אנו מחפשים רצף של תווים "th", שלפניהם התו "o" או התו "i".

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

$ echo "זהו מבחן" | awk "/ שלו הוא מבחן / (הדפס $ 0)" $ echo "זהו מבחן" | awk "/ שלו הוא מבחן / (הדפס 0 $)"

מצא מילים שיכולות להתחיל באות קטנה או גדולה

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

שלילת כיתות אופי

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

$ awk "/ [^ oi] th / (הדפס $ 0)" הקובץ שלי


מצא דמויות מחוץ לכיתה

במקרה זה, יימצאו רצפים של תווים "th", שלפניהם אין "o" ולא "i".

טווחים של דמויות

במחלקות תווים, אתה יכול לתאר טווחים של תווים באמצעות מקף:

$ awk "/ st / (הדפס $ 0)" שלי


תיאור מגוון תווים במחלקת תווים

בדוגמה זו, הביטוי הרגולרי מתאים לרצף התווים "st" שלפניו כל תו הממוקם, בסדר אלפביתי, בין התווים "e" ו-"p".

ניתן ליצור טווחים גם ממספרים:

$ echo "123" | awk "//" $ echo "12a" | אוקי "//"

ביטוי רגולרי כדי למצוא שלושה מספרים כלשהם

ניתן לכלול מספר טווחים במחלקת תווים:

$ awk "/ st / (הדפס $ 0)" שלי


כיתת תווים מרובה טווחים

ביטוי רגולרי זה יתאים לכל המחרוזות שלפניהן תווים בטווחים a-f ו-m-z.

שיעורי אופי מיוחדים

ל-BRE יש מחלקות תווים מיוחדות בהן תוכלו להשתמש בעת כתיבת ביטויים רגולריים:
  • [[: alpha:]] - מתאים לכל תו אלפביתי גדול או קטן.
  • [[: alnum:]] - מתאים לכל תו אלפאנומרי, כלומר תווים בטווחים 0-9, A-Z, a-z.
  • [[: ריק:]] - תואם רווח וטאב.
  • [[: ספרה:]] - כל תו דיגיטלי מ-0 עד 9.
  • [[: upper:]] - אותיות אלפביתיות גדולות - A-Z.
  • [[: תחתון:]] - אותיות אלפבית קטנות - a-z.
  • [[: print:]] - מתאים לכל תו שניתן להדפסה.
  • [[: פיסוק:]] - מתאים לסימני פיסוק.
  • [[:רווח:]] - תווי רווח לבן, בפרט - תווי רווח, טבלאות, תווי NL, FF, VT, CR.
אתה יכול להשתמש בשיעורים מיוחדים בתבניות כמו זה:

$ echo "abc" | awk "/ [[: alpha:]] / (הדפס $ 0)" $ echo "abc" | awk "/ [[: ספרה:]] / (הדפס $ 0)" $ echo "abc123" | awk "/ [[: ספרה:]] / (הדפס $ 0)"


שיעורי תווים מיוחדים בביטויים רגולריים

סמל כוכב

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

$ echo "מבחן" | awk "/ tes * t / (הדפס $ 0)" $ echo "tessst" | awk "/ tes * t / (הדפס $ 0)"


שימוש בתו * בביטויים רגולריים

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

$ echo "אני אוהב צבע ירוק" | awk "/ colou * r / (הדפס $ 0)" $ echo "אני אוהב צבע ירוק" | awk "/ colou * r / (הדפס $ 0)"

חפש מילה שיש לה איות שונה

בדוגמה זו, אותו ביטוי רגולרי מגיב הן למילה "צבע" והן למילה "צבע". זאת בשל העובדה שהסמל "u", שאחריו יש כוכבית, יכול להיעדר או להופיע מספר פעמים ברציפות.

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

$ awk "/this.*test/(הדפס $0)" שלי


תבנית המגיבה לכל מספר של כל תווים

במקרה זה, אין זה משנה כמה ואיזה תווים יש בין המילים "זה" ו"מבחן".

ניתן להשתמש בכוכבית גם עם מחלקות תווים:

$ echo "st" | awk "/ s * t / (הדפס $ 0)" $ echo "sat" | awk "/ s * t / (הדפס $ 0)" $ echo "set" | awk "/ s * t / (הדפס $ 0)"


שימוש בכוכבית עם כיתות תווים

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

ביטויים רגולריים של POSIX ERE

תבניות POSIX ERE שחלק מתוכניות השירות של לינוקס תומכות בהן עשויות להכיל תווים נוספים. כפי שכבר הוזכר, awk תומך בתקן זה, אבל sed לא.

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

▍סימן שאלה

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

$ echo "tet" | awk "/ tes? t / (הדפס $ 0)" $ echo "test" | awk "/ tes? t / (הדפס $ 0)" $ echo "test" | awk "/ tes? t / (הדפס $ 0)"


סימן שאלה בביטויים רגולריים

כפי שניתן לראות, במקרה השלישי האות "s" מופיעה פעמיים, כך שהביטוי הרגולרי אינו מגיב למילה "testst".

ניתן להשתמש בסימן השאלה גם עם כיתות תווים:

$ echo "tst" | awk "/ t? st / (הדפס $ 0)" $ echo "test" | awk "/ t? st / (הדפס $ 0)" $ echo "tast" | awk "/ t? st / (הדפס $ 0)" $ echo "taest" | awk "/ t? st / (הדפס $ 0)" $ echo "test" | awk "/ t? st / (הדפס $ 0)"


שיעורי סימן שאלה ודמות

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

▍ סמל פלוס

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

$ echo "מבחן" | awk "/ te + st / (הדפס $ 0)" $ echo "test" | awk "/ te + st / (הדפס $ 0)" $ echo "tst" | awk "/ te + st / (הדפס $ 0)"


סימן פלוס בביטויים רגולריים

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

$ echo "tst" | awk "/ t + st / (הדפס $ 0)" $ echo "test" | awk "/ t + st / (הדפס $ 0)" $ echo "teast" | awk "/ t + st / (הדפס $ 0)" $ echo "teeast" | awk "/ t + st / (הדפס $ 0)"


חוגי סימנים ותווים פלוס

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

▍סוגריים של תווים

הפלטה המסולסלת שבהן תוכל להשתמש בתבניות ERE דומות לדמויות שנדונו לעיל, אך הן מאפשרות לך לציין בצורה מדויקת יותר את המספר הנדרש של מופעים של הדמות שקודמת להן. ניתן לציין את המגבלה בשני פורמטים:
  • n הוא מספר המציין את המספר המדויק של מופעים לחיפוש
  • n, m - שני מספרים, המתפרשים כך: "לפחות n פעמים, אך לא יותר מ-m".
להלן דוגמאות לאפשרות הראשונה:

$ echo "tst" | awk "/ te (1) st / (הדפס $ 0)" $ echo "test" | awk "/ te (1) st / (הדפס $ 0)"

פלטה מתולתלת בדוגמאות, מצא מספר מדויק של מופעים

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

$ echo "tst" | awk "/ te (1,2) st / (הדפס $ 0)" $ echo "test" | awk "/ te (1,2) st / (הדפס $ 0)" $ echo "teest" | awk "/ te (1,2) st / (הדפס $ 0)" $ echo "teeest" | awk "/ te (1,2) st / (הדפס $ 0)"


המרווח שצוין בסוגרים מסולסלים

בדוגמה זו, התו "e" חייב להופיע בשורה 1 או 2 פעמים, ואז הביטוי הרגולרי יגיב לטקסט.

ניתן להשתמש בפלטה מתולתלת גם עם שיעורי אופי. להלן העקרונות שכבר מוכרים לך:

$ echo "tst" | awk "/ t (1,2) st / (הדפס $ 0)" $ echo "test" | awk "/ t (1,2) st / (הדפס $ 0)" $ echo "test" | awk "/ t (1,2) st / (הדפס $ 0)" $ echo "teeast" | awk "/ t (1,2) st / (הדפס $ 0)"


פלטה מתולתלת ושיעורי אופי

התבנית תגיב לטקסט אם היא מכילה את התו "a" או את התו "e" פעם או פעמיים.

▍ בוליאנית או סמל

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

$ echo "זהו מבחן" | awk "/ מבחן | בחינה / (הדפס $ 0)" $ echo "זוהי בחינה" | awk "/ מבחן | בחינה / (הדפס $ 0)" $ echo "זה משהו אחר" | awk "/ מבחן | בחינה / (הדפס $ 0)"


"או" בוליאני בביטויים רגולריים

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

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

$ echo "אהבתי" | awk "/ Like (Geeks)? / (הדפס $ 0)" $ echo "LikeGeeks" | awk "/ אוהב (חנונים)? / (הדפס $0)"


קיבוץ קטעי ביטוי רגולרי

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

דוגמאות מעשיות

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

▍ספירת מספר הקבצים

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

$ echo $ PATH | sed "s /: / / g"
הפקודה replace תומכת בביטויים רגולריים כתבניות לחיפוש טקסט. במקרה הזה הכל פשוט ביותר, אנחנו מחפשים סמל נקודתיים, אבל אף אחד לא טורח להשתמש כאן במשהו אחר - הכל תלוי במשימה הספציפית.
כעת עליך לעבור על הרשימה המתקבלת בלולאה ולבצע את הפעולות הדרושות כדי לספור את מספר הקבצים שם. הסכימה הכללית של התסריט תהיה כדלקמן:

Mypath = $ (הד $ PATH | sed "s /: / / g") עבור ספרייה ב- $ mypath do done
כעת נכתוב את הטקסט המלא של הסקריפט, באמצעות הפקודה ls כדי לקבל מידע על מספר הקבצים בכל אחת מהספריות:

#! / bin / bash mypath = $ (הד $ PATH | sed "s /: / / g") ספירה = 0 עבור ספרייה ב- $ mypath do check = $ (ספריית ls $) עבור פריט ב- $ check do count = $ [ספירת $ + 1] בוצע הד "ספריית $ - ספירת $" = 0 בוצע
בעת הפעלת הסקריפט, עלול להתברר שחלק מהספריות מ-PATH אינן קיימות, אולם הדבר לא ימנע ממנה לספור קבצים בספריות קיימות.


ספירת קבצים

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

▍בדיקת כתובות דואר אלקטרוני

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

[מוגן באימייל]
שם המשתמש, שם המשתמש, יכול להיות אלפאנומרי וכמה תווים אחרים. כלומר, זהו נקודה, מקף, קו תחתון, סימן פלוס. אחרי שם המשתמש מופיע הסימן @.

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

^(+)@
ניתן לקרוא את הביטוי הרגולרי הזה כך: "בתחילת שורה חייב להיות תו אחד לפחות מאלה שבקבוצה שצוינו בסוגריים מרובעים, ואחרי זה חייב להיות סימן @".

כעת הוא תור שם המארח - שם מארח. אותם כללים חלים כאן כמו עבור שם המשתמש, כך שהתבנית עבורו תיראה כך:

(+)
שם הדומיין ברמה העליונה כפוף לכללים מיוחדים. יכולים להיות תווים אלפביתיים בלבד, מהם חייבים להיות לפחות שניים (לדוגמה, דומיינים כאלה מכילים בדרך כלל קוד מדינה), ולא יותר מחמישה. כל זה אומר שהתבנית לבדיקת החלק האחרון של הכתובת תהיה כך:

\.({2,5})$
אתה יכול לקרוא את זה כך: "קודם כל חייבת להיות נקודה, ואז - מ-2 עד 5 תווים אלפביתיים, ואחרי זה השורה מסתיימת".

לאחר שהכנו את התבניות עבור החלקים הבודדים של הביטוי הרגולרי, בואו נרכיב אותם יחד:

^(+)@(+)\.({2,5})$
כעת כל שנותר הוא לבדוק מה קרה:

$echo" [מוגן באימייל]"| awk" /^(+)@(+)\.((2,5))$/(הדפס $ 0) "$ echo" [מוגן באימייל]"| awk" /^(+)@(+)\.((2,5))$/(הדפס $0) "


אימות כתובת דואר אלקטרוני באמצעות ביטויים רגולריים

העובדה שהטקסט המועבר ל-awk מודפס למסך פירושה שהמערכת זיהתה את כתובת המייל שבו.

תוצאות

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

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

קוראים יקרים! האם אתה משתמש בביטויים רגולריים בעת עיבוד טקסט בסקריפטים של שורת הפקודה?

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

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

מהם ביטויים רגולריים

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


לדעתנו, אפילו מתחיל מוחלט יבין מיד איך זה עובד ולמה אתה צריך את זה :) אם אתה לא כל כך מבין, פשוט המשך לקרוא והכל יסתדר.
ביטוי רגולרי הוא דפוס שתוכנות כמו sed או awk משתמשות בו כדי לסנן טקסט. תבניות משתמשות בתווי ASCII רגילים המייצגים את עצמם, ובמה שנקרא מטא-תווים, אשר ממלאים תפקיד מיוחד, למשל, המאפשרים לך להתייחס לקבוצות מסוימות של תווים.

סוגי ביטוי רגולרי

למימוש ביטוי רגולרי בסביבות שונות, כמו שפות תכנות כמו Java, Perl ו-Python, וכלי לינוקס כמו sed, awk ו-grep, יש מוזרויות מסוימות. תכונות אלו תלויות במה שנקרא מנועי regex שמפרשים דפוסים.
ישנם שני מנועי ביטוי רגולרי בלינוקס:
  • מנוע התומך בתקן POSIX Basic Regular Expression (BRE).
  • מנוע התומך בתקן POSIX Extended Regular Expression (ERE).
רוב כלי השירות של לינוקס תואמים לפחות את תקן POSIX BRE, אבל חלק מהכלים (כולל sed) מבינים רק תת-קבוצה של תקן BRE. אחת הסיבות למגבלה זו היא הרצון להפוך כלי עזר כאלה מהר ככל האפשר בעיבוד תמלילים.

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

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

ביטויים רגולריים של POSIX BRE

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

$ echo "זהו מבחן" | sed -n "/ test / p" $ echo "זהו מבחן" | awk "/ test / (הדפס $ 0)"

מחפש טקסט לפי דפוס ב-sed


מציאת טקסט לפי דפוס ב-awk

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

כשאתה עובד עם ביטויים רגולריים, זכור שהם תלויי רישיות:

$ echo "זהו מבחן" | awk "/ מבחן / (הדפס $ 0)" $ echo "זהו מבחן" | awk "/ test / (הדפס $ 0)"

ביטויים רגולריים הם תלויי רישיות

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

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

$ echo "זה שוב מבחן 2" | awk "/ בדיקה 2 / (הדפס $ 0)"

מצא פיסת טקסט המכילה רווחים ומספרים

מנוע הרקס מתייחס לרווחים כאל תווים רגילים.

סמלים מיוחדים

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

.*^${}\+?|()
אם יש צורך באחד מהם בתבנית, יהיה צורך להמלט ממנו באמצעות קו נטוי אחורי (לאחור) - \.

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

יש 10 $ על הכיס שלי
ניתן לזהות את סימן הדולר באמצעות דפוס כזה:

$ awk "/ \ $ / (הדפס $ 0)" שלי

שימוש בתו מיוחד בתבנית

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

$ echo "\ הוא תו מיוחד" | awk "/ \\ / (הדפס $ 0)"

קו נטוי אחורי בורח

למרות שהלוכסן קדימה אינו כלול ברשימת התווים המיוחדים לעיל, ניסיון להשתמש בו בביטוי רגולרי שנכתב עבור sed או awk יגרום לשגיאה:

$ echo "3/2" | awk "/// (הדפס $ 0)"

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

אם אתה צריך את זה, אתה צריך גם לסנן את זה:

$ echo "3/2" | awk "/ \ // (הדפס $ 0)"

נמלט קדימה סלאש

סמלי עוגן

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

$ echo "ברוכים הבאים לאתר likegeeks" | awk "/ ^ likegeeks / (הדפס $ 0)" $ echo "likegeeks website" | awk "/ ^ likegeeks / (הדפס $ 0)"

מציאת תבנית בתחילת שורה

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

$ awk "/ ^ זה / (הדפס $ 0)" הקובץ שלי


חפש דפוס בתחילת שורה בטקסט מקובץ

עם sed, אם תניח כובע בכל מקום בתוך התבנית, הוא יטופל כמו כל דמות רגילה אחרת:

$ echo "זה ^ זה מבחן" | sed -n "/ s ^ / p"

כיסוי לא בתחילת תבנית ב-sed

ב-awk, בעת שימוש באותה דפוס, יש לבצע בריחה מהתו הנתון:

$ echo "זה ^ זה מבחן" | awk "/ s \ ^ / (הדפס $ 0)"

כריכה לא בתחילת התבנית ב-awk

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

סימן הדולר - $, שהוא תו העוגן לסוף השורה, יעזור לנו בכך:

$ echo "זהו מבחן" | awk "/ test $ / (הדפס $ 0)"

מציאת טקסט בסוף שורה

ניתן להשתמש בשני תווי העוגן באותה תבנית. בואו נעבד את הקובץ myfile, שתוכנו מוצג באיור למטה, באמצעות הביטוי הרגולרי הבא:

$ awk "/ ^ זה מבחן $ / (הדפס $ 0)" הקובץ שלי


תבנית המשתמשת בתווים מיוחדים לתחילתה ולסופה של שורה

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

הנה איך לסנן שורות ריקות באמצעות תווי עוגן:

$ awk "! / ^ $ / (הדפס $ 0)" שלי
בתבנית זו השתמשתי בסמל השלילה, בסימן הקריאה -! . תבנית זו מחפשת שורות שאינן מכילות דבר בין ההתחלה לסוף השורה, וסימן הקריאה מדפיס רק קווים שאינם תואמים לתבנית.

סמל נקודה

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

$ awk "/.st/(הדפס $ 0)" שלי


שימוש בנקודה בביטויים רגולריים

כפי שניתן לראות מהנתונים המוצגים, רק שתי השורות הראשונות מהקובץ תואמות את התבנית, שכן הן מכילות את רצף התווים "st", שלפניו תו אחד נוסף, בעוד שהשורה השלישית אינה מכילה רצף מתאים, וכן ברביעי זה כן, אבל הוא ממש בתחילת השורה.

שיעורי אופי

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

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

$ awk "/ th / (הדפס $ 0)" שלי


תיאור מחלקה של תו ביטוי רגולרי

כאן אנו מחפשים רצף של תווים "th", שלפניהם התו "o" או התו "i".

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

$ echo "זהו מבחן" | awk "/ שלו הוא מבחן / (הדפס $ 0)" $ echo "זהו מבחן" | awk "/ שלו הוא מבחן / (הדפס 0 $)"

מצא מילים שיכולות להתחיל באות קטנה או גדולה

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

שלילת כיתות אופי

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

$ awk "/ [^ oi] th / (הדפס $ 0)" הקובץ שלי


מצא דמויות מחוץ לכיתה

במקרה זה, יימצאו רצפים של תווים "th", שלפניהם אין "o" ולא "i".

טווחים של דמויות

במחלקות תווים, אתה יכול לתאר טווחים של תווים באמצעות מקף:

$ awk "/ st / (הדפס $ 0)" שלי


תיאור מגוון תווים במחלקת תווים

בדוגמה זו, הביטוי הרגולרי מתאים לרצף התווים "st" שלפניו כל תו הממוקם, בסדר אלפביתי, בין התווים "e" ו-"p".

ניתן ליצור טווחים גם ממספרים:

$ echo "123" | awk "//" $ echo "12a" | אוקי "//"

ביטוי רגולרי כדי למצוא שלושה מספרים כלשהם

ניתן לכלול מספר טווחים במחלקת תווים:

$ awk "/ st / (הדפס $ 0)" שלי


כיתת תווים מרובה טווחים

ביטוי רגולרי זה יתאים לכל המחרוזות שלפניהן תווים בטווחים a-f ו-m-z.

שיעורי אופי מיוחדים

ל-BRE יש מחלקות תווים מיוחדות בהן תוכלו להשתמש בעת כתיבת ביטויים רגולריים:
  • [[: alpha:]] - מתאים לכל תו אלפביתי גדול או קטן.
  • [[: alnum:]] - מתאים לכל תו אלפאנומרי, כלומר תווים בטווחים 0-9, A-Z, a-z.
  • [[: ריק:]] - תואם רווח וטאב.
  • [[: ספרה:]] - כל תו דיגיטלי מ-0 עד 9.
  • [[: upper:]] - אותיות אלפביתיות גדולות - A-Z.
  • [[: תחתון:]] - אותיות אלפבית קטנות - a-z.
  • [[: print:]] - מתאים לכל תו שניתן להדפסה.
  • [[: פיסוק:]] - מתאים לסימני פיסוק.
  • [[:רווח:]] - תווי רווח לבן, בפרט - תווי רווח, טבלאות, תווי NL, FF, VT, CR.
אתה יכול להשתמש בשיעורים מיוחדים בתבניות כמו זה:

$ echo "abc" | awk "/ [[: alpha:]] / (הדפס $ 0)" $ echo "abc" | awk "/ [[: ספרה:]] / (הדפס $ 0)" $ echo "abc123" | awk "/ [[: ספרה:]] / (הדפס $ 0)"


שיעורי תווים מיוחדים בביטויים רגולריים

סמל כוכב

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

$ echo "מבחן" | awk "/ tes * t / (הדפס $ 0)" $ echo "tessst" | awk "/ tes * t / (הדפס $ 0)"


שימוש בתו * בביטויים רגולריים

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

$ echo "אני אוהב צבע ירוק" | awk "/ colou * r / (הדפס $ 0)" $ echo "אני אוהב צבע ירוק" | awk "/ colou * r / (הדפס $ 0)"

חפש מילה שיש לה איות שונה

בדוגמה זו, אותו ביטוי רגולרי מגיב הן למילה "צבע" והן למילה "צבע". זאת בשל העובדה שהסמל "u", שאחריו יש כוכבית, יכול להיעדר או להופיע מספר פעמים ברציפות.

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

$ awk "/this.*test/(הדפס $0)" שלי


תבנית המגיבה לכל מספר של כל תווים

במקרה זה, אין זה משנה כמה ואיזה תווים יש בין המילים "זה" ו"מבחן".

ניתן להשתמש בכוכבית גם עם מחלקות תווים:

$ echo "st" | awk "/ s * t / (הדפס $ 0)" $ echo "sat" | awk "/ s * t / (הדפס $ 0)" $ echo "set" | awk "/ s * t / (הדפס $ 0)"


שימוש בכוכבית עם כיתות תווים

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

ביטויים רגולריים של POSIX ERE

תבניות POSIX ERE שחלק מתוכניות השירות של לינוקס תומכות בהן עשויות להכיל תווים נוספים. כפי שכבר הוזכר, awk תומך בתקן זה, אבל sed לא.

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

▍סימן שאלה

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

$ echo "tet" | awk "/ tes? t / (הדפס $ 0)" $ echo "test" | awk "/ tes? t / (הדפס $ 0)" $ echo "test" | awk "/ tes? t / (הדפס $ 0)"


סימן שאלה בביטויים רגולריים

כפי שניתן לראות, במקרה השלישי האות "s" מופיעה פעמיים, כך שהביטוי הרגולרי אינו מגיב למילה "testst".

ניתן להשתמש בסימן השאלה גם עם כיתות תווים:

$ echo "tst" | awk "/ t? st / (הדפס $ 0)" $ echo "test" | awk "/ t? st / (הדפס $ 0)" $ echo "tast" | awk "/ t? st / (הדפס $ 0)" $ echo "taest" | awk "/ t? st / (הדפס $ 0)" $ echo "test" | awk "/ t? st / (הדפס $ 0)"


שיעורי סימן שאלה ודמות

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

▍ סמל פלוס

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

$ echo "מבחן" | awk "/ te + st / (הדפס $ 0)" $ echo "test" | awk "/ te + st / (הדפס $ 0)" $ echo "tst" | awk "/ te + st / (הדפס $ 0)"


סימן פלוס בביטויים רגולריים

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

$ echo "tst" | awk "/ t + st / (הדפס $ 0)" $ echo "test" | awk "/ t + st / (הדפס $ 0)" $ echo "teast" | awk "/ t + st / (הדפס $ 0)" $ echo "teeast" | awk "/ t + st / (הדפס $ 0)"


חוגי סימנים ותווים פלוס

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

▍סוגריים של תווים

הפלטה המסולסלת שבהן תוכל להשתמש בתבניות ERE דומות לדמויות שנדונו לעיל, אך הן מאפשרות לך לציין בצורה מדויקת יותר את המספר הנדרש של מופעים של הדמות שקודמת להן. ניתן לציין את המגבלה בשני פורמטים:
  • n הוא מספר המציין את המספר המדויק של מופעים לחיפוש
  • n, m - שני מספרים, המתפרשים כך: "לפחות n פעמים, אך לא יותר מ-m".
להלן דוגמאות לאפשרות הראשונה:

$ echo "tst" | awk "/ te (1) st / (הדפס $ 0)" $ echo "test" | awk "/ te (1) st / (הדפס $ 0)"

פלטה מתולתלת בדוגמאות, מצא מספר מדויק של מופעים

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

$ echo "tst" | awk "/ te (1,2) st / (הדפס $ 0)" $ echo "test" | awk "/ te (1,2) st / (הדפס $ 0)" $ echo "teest" | awk "/ te (1,2) st / (הדפס $ 0)" $ echo "teeest" | awk "/ te (1,2) st / (הדפס $ 0)"


המרווח שצוין בסוגרים מסולסלים

בדוגמה זו, התו "e" חייב להופיע בשורה 1 או 2 פעמים, ואז הביטוי הרגולרי יגיב לטקסט.

ניתן להשתמש בפלטה מתולתלת גם עם שיעורי אופי. להלן העקרונות שכבר מוכרים לך:

$ echo "tst" | awk "/ t (1,2) st / (הדפס $ 0)" $ echo "test" | awk "/ t (1,2) st / (הדפס $ 0)" $ echo "test" | awk "/ t (1,2) st / (הדפס $ 0)" $ echo "teeast" | awk "/ t (1,2) st / (הדפס $ 0)"


פלטה מתולתלת ושיעורי אופי

התבנית תגיב לטקסט אם היא מכילה את התו "a" או את התו "e" פעם או פעמיים.

▍ בוליאנית או סמל

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

$ echo "זהו מבחן" | awk "/ מבחן | בחינה / (הדפס $ 0)" $ echo "זוהי בחינה" | awk "/ מבחן | בחינה / (הדפס $ 0)" $ echo "זה משהו אחר" | awk "/ מבחן | בחינה / (הדפס $ 0)"


"או" בוליאני בביטויים רגולריים

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

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

$ echo "אהבתי" | awk "/ Like (Geeks)? / (הדפס $ 0)" $ echo "LikeGeeks" | awk "/ אוהב (חנונים)? / (הדפס $0)"


קיבוץ קטעי ביטוי רגולרי

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

דוגמאות מעשיות

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

▍ספירת מספר הקבצים

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

$ echo $ PATH | sed "s /: / / g"
הפקודה replace תומכת בביטויים רגולריים כתבניות לחיפוש טקסט. במקרה הזה הכל פשוט ביותר, אנחנו מחפשים סמל נקודתיים, אבל אף אחד לא טורח להשתמש כאן במשהו אחר - הכל תלוי במשימה הספציפית.
כעת עליך לעבור על הרשימה המתקבלת בלולאה ולבצע את הפעולות הדרושות כדי לספור את מספר הקבצים שם. הסכימה הכללית של התסריט תהיה כדלקמן:

Mypath = $ (הד $ PATH | sed "s /: / / g") עבור ספרייה ב- $ mypath do done
כעת נכתוב את הטקסט המלא של הסקריפט, באמצעות הפקודה ls כדי לקבל מידע על מספר הקבצים בכל אחת מהספריות:

#! / bin / bash mypath = $ (הד $ PATH | sed "s /: / / g") ספירה = 0 עבור ספרייה ב- $ mypath do check = $ (ספריית ls $) עבור פריט ב- $ check do count = $ [ספירת $ + 1] בוצע הד "ספריית $ - ספירת $" = 0 בוצע
בעת הפעלת הסקריפט, עלול להתברר שחלק מהספריות מ-PATH אינן קיימות, אולם הדבר לא ימנע ממנה לספור קבצים בספריות קיימות.


ספירת קבצים

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

▍בדיקת כתובות דואר אלקטרוני

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

[מוגן באימייל]
שם המשתמש, שם המשתמש, יכול להיות אלפאנומרי וכמה תווים אחרים. כלומר, זהו נקודה, מקף, קו תחתון, סימן פלוס. אחרי שם המשתמש מופיע הסימן @.

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

^(+)@
ניתן לקרוא את הביטוי הרגולרי הזה כך: "בתחילת שורה חייב להיות תו אחד לפחות מאלה שבקבוצה שצוינו בסוגריים מרובעים, ואחרי זה חייב להיות סימן @".

כעת הוא תור שם המארח - שם מארח. אותם כללים חלים כאן כמו עבור שם המשתמש, כך שהתבנית עבורו תיראה כך:

(+)
שם הדומיין ברמה העליונה כפוף לכללים מיוחדים. יכולים להיות תווים אלפביתיים בלבד, מהם חייבים להיות לפחות שניים (לדוגמה, דומיינים כאלה מכילים בדרך כלל קוד מדינה), ולא יותר מחמישה. כל זה אומר שהתבנית לבדיקת החלק האחרון של הכתובת תהיה כך:

\.({2,5})$
אתה יכול לקרוא את זה כך: "קודם כל חייבת להיות נקודה, ואז - מ-2 עד 5 תווים אלפביתיים, ואחרי זה השורה מסתיימת".

לאחר שהכנו את התבניות עבור החלקים הבודדים של הביטוי הרגולרי, בואו נרכיב אותם יחד:

^(+)@(+)\.({2,5})$
כעת כל שנותר הוא לבדוק מה קרה:

$echo" [מוגן באימייל]"| awk" /^(+)@(+)\.((2,5))$/(הדפס $ 0) "$ echo" [מוגן באימייל]"| awk" /^(+)@(+)\.((2,5))$/(הדפס $0) "


אימות כתובת דואר אלקטרוני באמצעות ביטויים רגולריים

העובדה שהטקסט המועבר ל-awk מודפס למסך פירושה שהמערכת זיהתה את כתובת המייל שבו.

תוצאות

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

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

קוראים יקרים! האם אתה משתמש בביטויים רגולריים בעת עיבוד טקסט בסקריפטים של שורת הפקודה?