תחי ישראל - אין לנו ארץ אחרת

תחי ישראל -אין לנו ארץ אחרת

מדריך sed לעריכת טקסט שורה אחת בכל פעם

מחבר:
בתאריך:

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

Linux sed command tutorial

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

התחביר הבסיסי של פקודת sed הוא:

sed [options] [command] [input file]
  • האופציות options משנות את התנהגות הפקודה sed.
  • ה-input הוא לרוב מסמך טקסט שאנחנו מעוניינים לעבוד איתו.

כמה אופציות שימושיות במיוחד כשעובדים עם sed הם:

  • s - לאיתור והחלפת טקסט.
  • p - להדפסה.
  • i - להכנסת טקסט.
  • d - למחיקת טקסט.

 

שימוש ב-sed כדי למצוא ולהחליף טקסט

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

ניקח את קובץ הטקסט הבא בתור דוגמה:

$ cat my.log
2023-12-01 12:05:23 INFO: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 Warn: Disk space is running low.
2023-12-01 13:20:14 INFO: User 'John' logged in.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:35:29 INFO: Application shutdown initiated.
2023-12-01 13:40:05 WARN: Security alert - multiple failed login attempts.

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

$ sed 's/WARN/CRITICAL/g' my.log

הפקודה תחפש בתוך המסמך my.log את המחרוזת "WARN" ותחליף עם המחרוזת "CRITICAL" לצורך הצגת הפלט. הדגל g מורה לפקודה sed החליף את הביטוי בכל מקום במסמך.

  • 's' היא האופציה המשמשת לחיפוש ולהחלפה של טקסט search and replace
  • 'g' - קיצור של globally דגל המשמש לביצוע הפעולה בכל מקום בטקסט. ללא הדגל g הפקודה sed תחליף את המקרה הראשון שהיא מוצאת בכל שורה, ולא תחליף את כל המקרים בכל הקובץ.
  • צריך לשים לב, ההחלפה אינה במסמך אלא בפלט בלבד.

הפלט של הרצת הפקודה בטרמינל:

2023-12-01 12:05:23 INFO: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 Warn: Disk space is running low.
2023-12-01 13:20:14 INFO: User 'John' logged in.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:35:29 INFO: Application shutdown initiated.
2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.
  • מונח החיפוש "WARN" הוחלף בכל מקום שבו הוא הופיע במסמך.
  • הטקסט "Warn" לא הוחלף בגלל שהוא מופיע באותיות קטנות בעוד מונח החיפוש מופיע באותיות גדולות "WARN".

 

כדי להחליף את הביטוי בכל מקום במסמך בלי להתחשב בגודל האות נשתמש בצירוף הדגלים `g` (גלובלי) ו-`i` (ר"ת של case Insensitive):

$ sed 's/warn/CRITICAL/gi' my.log

התוצאה:

2023-12-01 12:05:23 INFO: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 CRITICAL: Disk space is running low.
2023-12-01 13:20:14 INFO: User 'John' logged in.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:35:29 INFO: Application shutdown initiated.
2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.
  • אכן כל המקרים של הביטוי "warn", ללא תלות בגודל האות, הוחלפו ב-"CRITICAL".

 

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

בד"כ משתמשים בפקודה sed על קבצי לוג שאותם לא רוצים לשנות. אם בכל זאת רוצים לערוך מסמך אז (כמעט) תמיד עדיף ליצור מסמך נוסף שיכיל את השינויים הרצויים ולהשאיר את הקובץ המקורי כמו שהוא.

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

$ sed 's/warn/CRITICAL/gi' my.log > new.log
  • `my.log` הוא קובץ המקור בעוד `new.log` הוא הקובץ אליו רוצים להפנות את פלט הפקודה.

התוצאה היא שקובץ המקור, ישאר כמו שהוא ובמקביל הפקודה sed תיצור באותה תיקייה מסמך בשם שונה שיכלול את השינויים.

 

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

$ diff my.log new.log

התוצאה:

3c3
< 2023-12-01 12:15:32 Warn: Disk space is running low.
---
> 2023-12-01 12:15:32 CRITICAL: Disk space is running low.
9c9
< 2023-12-01 13:40:05 WARN: Security alert - multiple failed login attempts.
---
> 2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.
  • הרצת הפקודה diff הציגה את השינויים בשורות 3 ו-9 של המסמך.

 

אם בכל זאת רוצים לשנות את הקובץ שעליו עובדים, וזה בד"כ לא דבר מומלץ, אז משתמשים באופציה `i` שעושה עריכה in-place. לדוגמה:

$ sed -i 's/warn/CRITICAL/gi' my.log

 

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

נעזר בפקודה cat להצגת המסמך כולל מספרי השורות:

$ cat -n my.log

התוצאה:

     1	2023-12-01 12:05:23 INFO: Application started successfully.
     2	2023-12-01 12:10:45 ERROR: Connection error occurred.
     3	2023-12-01 12:15:32 CRITICAL: Disk space is running low.
     4	2023-12-01 13:20:14 INFO: User 'John' logged in.
     5	
     6	2023-12-01 13:25:55 DEBUG: Processing data for task #123.
     7	2023-12-01 13:30:18 ERROR: Database connection lost.
     8	2023-12-01 13:35:29 INFO: Application shutdown initiated.
     9	2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.

 

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

לדוגמה, נעזר בפקודה sed ע"מ להדפיס רק את שורה 6:

$ sed -n '6p' my.log

התוצאה:

2023-12-01 13:25:55 DEBUG: Processing data for task #123.

 

אפשר לבחור להדפיס מספר שורות במקום רק אחת.

ניתן לציין טווח של שורות עליהם נרצה להפעיל את הפקודה sed. לדוגמה, שורות 2 - 6:

$ sed -n '2,6p' my.log

התוצאה:

2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 CRITICAL: Disk space is running low.
2023-12-01 13:20:14 INFO: User 'John' logged in.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.

הסבר הפקודה:

  • האופציה `-n` - מונעת הדפסה אוטומטית. הסיבה בגללה האופציה שימושית היא שבכל פעם שמשתמשים בפקודה sed התוצאה מודפסת אוטומטית למסך אבל לא תמיד ההתנהגות הזו רצויה לנו, ולפעמים נעדיף שההדפסה תהיה רק לפי דרישה מפורשת. (אם זה לא ברור אז נא לנסות את הפקודה ללא האופציה)

  • `2,6p` - זה החלק שמבצע הלכה למעשה את הדפסת טווח השורות כאשר `p` מורה על הדפסה באופן מפורש.

 

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

$ sed -n '1~3p' my.log

 

מאוד חשוב לדעת להפעיל את הפקודה sed רק על שורות שמעניינות אותנו. להדפסת כל השורות שיש בהם את מונח החיפוש המבוקש, שלצורך הדוגמה הוא "task #123":

$ sed -n '/task #123/p' my.log
  • האופציה `-n` - למניעת הדפסה אוטומטית.

  • הביטוי `/task #123/` - מציין את מה שצריך לחפש.

  • `p` - בשביל להדפיס את התוצאה.

התוצאה:

2023-12-01 13:25:55 DEBUG: Processing data for task #123.

 

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

$ sed -n '/Disk space/,+3p' my.log
  • האופציה `-n` - למניעת הדפסה אוטומטית.

  • הביטוי `/Disk space/` - מציין את הביטוי אותו מעוניינים למצוא.

  • `+3p` - להדפסת השורות בהם נמצא הביטוי המבוקש וטווח של 3 שורות לאחר מכן.

 

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

$ sed -n '/12:[0-5][0-9]:[0-5][0-9]/p' my.log

התוצאה:

2023-12-01 12:05:23 INFO: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 CRITICAL: Disk space is running low.

 

 

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

 

שימוש ב-sed כדי להוסיף טקסט

ניתן להשתמש בפקודה sed כדי להוסיף טקסט.

הנה דוגמה כדי להמחיש כיצד להשתמש ב-sed כדי להוסיף טקסט:

$ sed '3 i\This line was appended using sed' my.log
  • `3` - מציין את מספר השורה שיש להוסיף אחריה את הטקסט.

  • `i\` - מציין את הטקסט אותו יש להוסיף.

התוצאה:

2023-12-01 12:05:23 INFO: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
This line was appended using sed
2023-12-01 12:15:32 CRITICAL: Disk space is running low.
2023-12-01 13:20:14 INFO: User 'John' logged in.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:35:29 INFO: Application shutdown initiated.
2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.

 

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

$ sed '/shutdown/a Should be checked' my.log

הפקודה אומרת שאחרי כל שורה שמכילה את ביטוי החיפוש shutdown יש להדביק את השורה Should be checked.

  • `/shutdown/`: מציין את הביטוי אותו יש לחפש.

  • `a`: קיצור של "append" מציין שיש להוסיף את הטקסט המצויין רק אחרי.

  • `Should be checked`: הטקסט שיש להוסיף בשורות אשר מתחת לשורות שתואמות לביטוי.

התוצאה:

2023-12-01 12:05:23 INFO: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 CRITICAL: Disk space is running low.
2023-12-01 13:20:14 INFO: User 'John' logged in.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:35:29 INFO: Application shutdown initiated.
Should be checked
2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.

לפעמים אנחנו מעדיפים להוסיף את הטקס לפני ההתאמה. נחליף את "a" ב-"i" בשביל להוסיף את הטקסט לפני במקום אחרי. לדוגמה:

$ sed '/shutdown/i Should be checked' my.log
  • `/shutdown/`: מציין את הביטוי אותו יש לחפש.

  • `i`: קיצור של "insert" מציין שיש להוסיף את הטקסט המצויין עוד לפני השורות בהם ישנה התאמה.

 

מחיקה של טקסט באמצעות הפקודה sed

ניתן להשתמש בפקודה sed כדי למחוק טקסט באמצעות הפקודה `d` (קיצור של delete). להלן התחביר הבסיסי:

sed 'patternToDelete/d' [filename]
  • כאן, patternToDelete הוא הביטוי הרגולרי או הדפוס שאתה רוצה להתאים, ושורות התואמות את הדפוס יימחקו.

אם אתה רוצה למחוק שורות המכילות את הטקסט "ATTENTION:", אתה יכול להשתמש בפקודה sed הבאה:

$ sed '/ATTENTION:/d' my.log

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

2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 CRITICAL: Disk space is running low.

2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.

 

אפשר למחוק שורות מסויימות. לדוגמה, למחוק את טווח השורות 1 עד 3:

$ sed '1, 3 d' my.log

 

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

$ sed '2,6{/^$/d}' my.log

התוצאה:

2023-12-01 12:05:23 ATTENTION: Application started successfully.
2023-12-01 12:10:45 ERROR: Connection error occurred.
2023-12-01 12:15:32 CRITICAL: Disk space is running low.
2023-12-01 13:20:14 ATTENTION: User 'John' logged in.
2023-12-01 13:25:55 DEBUG: Processing data for task #123.
2023-12-01 13:30:18 ERROR: Database connection lost.
2023-12-01 13:35:29 ATTENTION: Application shutdown initiated.
2023-12-01 13:40:05 CRITICAL: Security alert - multiple failed login attempts.

 

שילוב sed ביחד עם awk

אפשר להפנות את הפלט של sed לפקודה אחרת כדי לקבל את מה שרוצים.

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

sed 's/^\[.*\] //' error_log.log | awk '!seen[$0]++' > filtered_log.log
  • בפועל, הקוד מתעלם מחלקה הראשון של השורה התחום בין סוגריים מרובעים כדי להתגבר על הבעיה של פורמטים שונים של תאריכים

  • החלק האחרון של הפקודה רושם את התוצאה לתוך קובץ נפרד.

 

מדריכים נוספים בסדרה ללימוד לינוקס

מדריך Awk - פקודה של Bash שהיא גם (סוג של) שפת תכנות

עריכת קבצים על Linux באמצעות vim

לינוקס - צינורות והפניות

 

לכל המדריכים בסדרת הלינוקס

 

אהבתם? לא אהבתם? דרגו!

0 הצבעות, ממוצע 0 מתוך 5 כוכבים

 

 

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

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

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

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

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

הוסף תגובה חדשה

 

 

ענה על השאלה הפשוטה הבאה כתנאי להוספת תגובה:

איך קוראים בעברית לצ`ופצ`יק של הקומקום?