سطح مقدماتی (Beginner Level)
ماژول shlex (مخفف Shell Lexical analysis) یکی از ماژولهای استاندارد و بسیار کاربردی پایتون است. هدف اصلی این ماژول، تجزیه و تحلیل رشتههای متنی (String) شبیه به روشی است که Shell یونیکس (مانند Bash) آنها را میخواند.
اگر شما قصد دارید برنامهای بنویسید که دستورات ورودی کاربر را پردازش کند، یا میخواهید رشتهای را برای استفاده در ماژول subprocess آماده کنید، shlex ابزار اصلی شماست.
۱. چرا از split() معمولی استفاده نکنیم؟
بسیاری از مبتدیان برای جدا کردن کلمات یک دستور از متد str.split() استفاده میکنند. اما این روش زمانی که در متن "فاصله" (Space) داخل کوتیشن داشته باشیم، شکست میخورد.
ماژول shlex هوشمند است و میداند که فضاهای خالی داخل کوتیشنها نباید جدا شوند.
مثال اول: مشکل متد split معمولی (Code Snippet)
در این مثال میبینید که منطق ساده پایتون برای دستورات پیچیده کافی نیست.
# Static Code: This logic is flawed for shell commands
command = 'git commit -m "Fixing bugs"'
parts = command.split()
# Result: ['git', 'commit', '-m', '"Fixing', 'bugs"']
# اشتباه است! پیام کامیت دو تکه شده است.
مثال دوم: استفاده صحیح از shlex.split (Interactive)
در این مثال، همان دستور بالا را با shlex پردازش میکنیم تا نتیجه صحیح را ببینید.
مثال سوم: مدیریت کاراکترهای خاص (Interactive)
shlex به صورت خودکار از کاراکترهای Escape (مثل \) نیز پشتیبانی میکند.
۲. خواندن دستورات از فایل یا ورودی
گاهی اوقات ورودی شما یک رشته ساده نیست، بلکه جریانی از دادههاست. shlex میتواند مستقیماً روی ورودیها کار کند.
مثال اول: ساختار کلی (Static)
این کد نشان میدهد چگونه میتوان یک شیء shlex ساخت، اما بدون ورودی اجرا نمیشود.
import shlex
def create_parser(input_text):
lexer = shlex.shlex(input_text)
return lexer
مثال دوم: خواندن توکن به توکن (Interactive)
در اینجا ما یک رشته را به عنوان یک فایل شبیهسازی میکنیم و توکنهای آن را یکییکی میخوانیم.
سطح پیشرفته (Professional Level)
در سطح حرفهای، shlex فقط برای جدا کردن رشتهها نیست؛ بلکه ابزاری حیاتی برای امنیت سایبری (جلوگیری از تزریق کد) و ساخت پارسرهای سفارشی است. همچنین در نسخههای جدید پایتون قابلیتهای معکوس (تبدیل لیست به رشته شل) اضافه شده است.
۱. امنیت و جلوگیری از Shell Injection با shlex.quote
زمانی که میخواهید یک نام فایل یا ورودی کاربر را در یک دستور Shell اجرا کنید، اگر کاربر ورودی مخربی مثل ; rm -rf / وارد کند، سیستم شما در خطر است. تابع shlex.quote() (در پایتون ۳.۳+) ورودی را به گونهای تغییر میدهد که در Shell فقط به عنوان یک "رشته" شناخته شود، نه دستور اجرایی.
مثال اول: مفهوم ناامن بودن (Static)
کد زیر نشان میدهد چگونه عدم استفاده از quote میتواند خطرناک باشد.
import os
filename = "file; rm -rf /"
# DANGEROUS: This would delete files!
# os.system(f"ls -l {filename}")
مثال دوم: ایمنسازی ورودی (Interactive)
در این مثال میبینیم که shlex.quote چگونه ورودی خطرناک را خنثی میکند.
۲. بازسازی دستور با shlex.join
این متد (که در پایتون ۳.۸ اضافه شد) دقیقاً برعکس split عمل میکند. یعنی یک لیست از آرگومانها را میگیرد و یک رشته واحد و ایمن برای اجرا در Shell تولید میکند.
مثال اول: ترکیب لیست (Interactive)
مثال دوم: کاربرد عملی در Docker (Interactive)
فرض کنید میخواهید یک دستور docker exec بسازید.
۳. شخصیسازی کلاس shlex (Custom Parser)
کلاس shlex بسیار منعطف است. شما میتوانید تعریف کنید چه کاراکترهایی به عنوان کامنت (#)، چه کاراکترهایی به عنوان جداکننده و چه کاراکترهایی به عنوان فضای خالی در نظر گرفته شوند. این برای ساخت زبانهای پیکربندی کوچک (mini-languages) عالی است.
مثال اول: تغییر کاراکتر کامنت (Interactive)
در شل معمولی # کامنت است، اما شاید در فایل فرمت خاص شما % کامنت باشد.
مثال دوم: کنترل POSIX Mode
حالت posix=True (پیشفرض در split) رفتار استاندارد یونیکس را دارد. اما اگر posix=False باشد، رفتار قدیمیتر و سازگارتر با ویندوز یا سیستمهای قدیمی را شبیهسازی میکند. تفاوت اصلی در نحوه برخورد با کوتیشنها و کاراکترهای Wildcard است.
۴. نکات فنی و Best Practices
- همیشه برای
subprocess: هنگام استفاده ازsubprocess.run(..., shell=True)حتماً ازshlex.quoteاستفاده کنید، هرچند پیشنهاد میشود همیشهshell=Falseاستفاده کرده و لیست آرگومانها را به subprocess بدهید. - Unicode: ماژول
shlexدر پایتون ۳ کاملاً با یونیکد سازگار است، اما در حالتposix=Falseممکن است روی بایتهای خاصی رفتار متفاوتی نشان دهد. - مدیریت خطا: متد
splitممکن استValueErrorبرگرداند اگر کوتیشنها بسته نشده باشند (مثلاً"open quote).