ריפוד באפסים עם ביטוי רגולארי

20/10/2018

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

1. ריפוד לשתי ספרות

ניקח את הקובץ הבא המכיל רשימת שירים באלבום:

$ cat demo.txt
1. In the Flesh?
2. The Thin Ice
3. Another Brick in the Wall (Part I)
4. The Happiest Days of Our Lives
5. Another Brick in the Wall (Part II)
6. Mother
7. Goodbye Blue Sky
8. Empty Spaces
9. Young Lust
10. One of My Turns
11. Don't Leave Me Now
12. Another Brick in the Wall (Part III)
13. Goodbye Cruel World

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

$ cat demo.txt | sed  's/^\([0-9]\)\./0\1./'
01. In the Flesh?
02. The Thin Ice
03. Another Brick in the Wall (Part I)
04. The Happiest Days of Our Lives
05. Another Brick in the Wall (Part II)
06. Mother
07. Goodbye Blue Sky
08. Empty Spaces
09. Young Lust
10. One of My Turns
11. Don't Leave Me Now
12. Another Brick in the Wall (Part III)
13. Goodbye Cruel World

2. ריפוד באפסים כשהמספר באמצע השורה

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

$ cat demo.txt
3. Another 1 Brick in the Wall (Part I)
4. The Happiest 2 Days of Our Lives
5. Another Brick 3 in the Wall (Part II)
7. Goodbye Blue 4 Sky
9. Young 25 Lust

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

$ cat demo.txt | sed  's/\b\([0-9]\)\b/0\1/g'
03. Another 01 Brick in the Wall (Part I)
04. The Happiest 02 Days of Our Lives
05. Another Brick 03 in the Wall (Part II)
07. Goodbye Blue 04 Sky
09. Young 25 Lust

החלפת תחילת השורה ב \b איפשרה לנו להחליף גם מספרים שהופיעו באמצע השורה. התוספת של /g גרמה ל sed להחליף את כל המופעים בשורה ולכן הוחלפו גם המספר בתחילת השורה וגם זה שבאמצע.

3. ריפוד ל-3 ספרות

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

$ cat demo.txt | sed  's/\b\([0-9]\{1,2\}\)\b/0\1/g' | sed  's/\b\([0-9]\{1,2\}\)\b/0\1/g'

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

4. או awk

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

$ cat demo.txt | awk '{ $1 = sprintf("%.3d.", $1); print; }'
001. In the Flesh?
002. The Thin Ice
003. Another Brick in the Wall (Part I)
004. The Happiest Days of Our Lives
005. Another Brick in the Wall (Part II)
006. Mother
007. Goodbye Blue Sky
008. Empty Spaces
009. Young Lust
010. One of My Turns
011. Don't Leave Me Now
012. Another Brick in the Wall (Part III)
013. Goodbye Cruel World
140. bye bye

רעיונות נוספים? ספרו לי בתגובות.