فصل ۲۰ – پردازش متن
بخش عمدهای از کار در محیط خط فرمان با متن سروکار دارد.
فایلهای پیکربندی، گزارشها، خروجی برنامهها و بسیاری از دادههای دیگر همگی متنی هستند.
ابزارهای یونیکس برای فیلتر کردن، تبدیل و تحلیل متن شهرت دارند؛ آنها را میتوان زنجیروار ترکیب کرد و وظایف پیچیده را به روشی ساده انجام داد.
در این فصل خواهیم دید چگونه میتوان جریانهای داده را با فیلترهای گوناگون تغییر داد و اطلاعات مورد نیاز را به دست آورد.
مباحث اصلی عبارتاند از:
- استفاده از
cut،pasteوjoinبرای انتخاب و ترکیب ستونها. - بهرهگیری از
sort،uniqوcommبرای مرتبسازی و حذف خطوط تکراری. - ابزارهای شمارش مانند
wcوnl. - آشنایی با
tr،expandوfmtبرای قالببندی سریع متن.
انتخاب ستونها با cut
دستور cut برای استخراج بخشهایی از هر خط به کار میرود.
به کمک گزینهٔ -f میتوان ستونها را براساس جداکنندهٔ مشخص استخراج کرد.
برای نمونه اگر فایل sales.csv شامل مقادیر جداشده با کاما باشد، میتوان ستون دوم و چهارم را اینگونه برداشت:
cut -d',' -f2,4 sales.csv
با -c میتوان محدودهٔ کاراکتری تعیین کرد و با --complement ستونهای به جز موارد خواستهشده را گرفت.
چسباندن ستونها با paste
اگر بخواهیم فایلهایی را به صورت ستونبهستون کنار هم قرار دهیم، paste مفید است.
مثلاً دو فایل names و phones را ترکیب کنیم:
paste names phones
به طور پیشفرض از تب به عنوان جداکننده استفاده میکند؛ با گزینهٔ -d میتوان جداکنندهٔ دیگری تعیین کرد.
join برای دادههای جدولی
join شبیه عملیات «پیوستن» در پایگاههای داده است و سطرهایی را که کلید مشترک دارند ادغام میکند.
پیش از استفاده باید فایلها براساس ستون کلید مرتب شده باشند.
نمونه:
join -t',' -1 1 -2 1 customers.csv orders.csv
گزینهٔ -1 و -2 شمارهٔ ستون کلید را مشخص میکند و -t جداکننده را تعیین میکند.
مرتبسازی و حذف تکرار
دستور sort خطوط را مرتب میکند.
میتوانیم نوع مرتبسازی را با گزینههای مختلف تعیین کنیم:
-nمرتبسازی عددی.-rترتیب معکوس.-kمشخص کردن کلید مرتبسازی.-uحذف خطوط تکراری.
مثال:
sort -t',' -k3,3n -k1,1 sales.csv
این فرمان ابتدا براساس ستون سوم به صورت عددی و سپس ستون اول به شکل الفبایی مرتب میکند.
برای حذف خطوط تکراری پس از مرتبسازی از uniq استفاده میشود:
sort names.txt | uniq
گزینهٔ -c در uniq تعداد تکرار هر خط را نشان میدهد و -d فقط خطوطی را چاپ میکند که بیشتر از یک بار دیده شدهاند.
همچنین comm سه فایل خروجی تولید میکند که اشتراک و اختلاف دو فایل مرتبشده را نمایش میدهد.
شمارش و شمارهگذاری خطوط
wcتعداد خطوط (-l)، واژهها (-w) و کاراکترها (-c) را گزارش میکند.nlخطوط را شمارهگذاری میکند و نسبت به خطوط خالی یا بلوکها گزینههای بیشتری دارد.
برای شمارش همهٔ فایلهای متنی در دایرکتوری:
wc -l *.txt
اگر بخواهیم تنها تعداد کل خطوط را بدانیم، گزینهٔ --total=only در wc مفید است.
تبدیل کاراکترها با tr
tr کاراکترها را جایگزین یا حذف میکند.
برای مثال تبدیل حروف کوچک به بزرگ:
tr '[:lower:]' '[:upper:]' < report.txt
یا حذف کاراکترهای غیرقابل چاپ:
tr -cd '\11\12\15\40-\176' < data.txt
گزینهٔ -s توالیهای تکراری را فشرده میکند، مثلاً چند فاصلهٔ پشت سر هم را به یکی تبدیل میکند.
تب و فاصله
expand تبها را به فاصله تبدیل و unexpand برعکس عمل میکند.
این ابزارها هنگام هماهنگسازی قالب فایلهای کد منبع مفید هستند.
expand -t4 source.c > source.spaces.c
تقسیم فایلها با split و csplit
هنگام کار با فایلهای بزرگ ممکن است بخواهیم آنها را به بخشهای کوچکتر تقسیم کنیم.
دستور split فایل را براساس اندازه یا تعداد خطوط تکهتکه میکند:
split -b 10M huge.log huge-
این فرمان فایل huge.log را به بلوکهای ۱۰ مگابایتی با نامهای huge-aa, huge-ab و ... تقسیم میکند.
با گزینهٔ -l میتوان تعداد خطوط را مشخص کرد و با -d از شمارهگذاری عددی استفاده نمود.
برای تقسیم براساس الگوها، csplit مناسبتر است. این ابزار بر اساس regex مرزهای فایل را پیدا میکند:
csplit report.txt '/^Chapter [0-9]+/' '{*}'
در مثال بالا هر فصل در فایل جداگانهای ذخیره میشود. گزینهٔ '{*}' به csplit میگوید تا پایان فایل هر بار که الگو یافت شد این کار را تکرار کند. پس از تقسیم، میتوانیم فایلهای حاصل را پردازش یا آرشیو کنیم.
شکستن و ترکیب خطوط
fmtپاراگرافها را تا طول مشخصی میشکند.foldخطوط طولانی را بدون توجه به کلمات میشکند.prفایلها را برای چاپ آماده میکند و سرصفحه و شمارهٔ صفحه میافزاید.
نمونه:
fmt -w 72 letter.txt > letter_wrapped.txt
ترکیب ابزارها در خط لوله
قدرت واقعی ابزارهای پردازش متن زمانی آشکار میشود که آنها را زنجیر کنیم.
مثلاً برای یافتن پرفروشترین کالا بر اساس دادهٔ CSV:
cut -d',' -f2,5 sales.csv \
| sort -t',' -k2,2nr \
| head -n 10
یا برای استخراج دامنهٔ ایمیلها از فایل متنی:
grep -E -o '[[:alnum:]_.+-]+@[[:alnum:].-]+' contacts.txt \
| cut -d'@' -f2 \
| sort \
| uniq -c \
| sort -nr
تمرین
برای تسلط بیشتر روی ابزارهای پردازش متن، سناریوهای روزمره را تمرین کنید:
- فایلی از لاگ وب بگیرید، فقط کدهای وضعیت (status code) را استخراج کنید و تعداد هر کد را بشمارید.
- فهرستی از کارمندان با حقوق دریافتی تهیه کنید و متوسط حقوق را حساب کنید.
- از
joinاستفاده کنید تا دو فایل شامل کد محصول و موجودی انبار را ترکیب کنید و فقط محصولاتی را نمایش دهید که موجودیشان کمتر از حداقل تعریفشده است.
هرچه بیشتر این ابزارها را کنار هم قرار دهید، خلاقیت بیشتری در حل مسائل متنی پیدا میکنید.
مطالعهٔ بیشتر
- بستهٔ GNU Coreutils شامل بسیاری از این ابزارهاست؛ صفحههای راهنما (
man cut,man paste,man splitو غیره) مثالهای فراوانی دارند. - پروژهٔ The Open Group POSIX تعریف رسمی نحوهٔ عملکرد این دستورات را ارائه میدهد.
- برای سناریوهای پیچیدهتر پردازش متن، مطالعهٔ ابزارهای
perl,pythonو کتابخانهٔpandasمیتواند دید گستردهتری بدهد.