سؤال

عند استخدام os.system()، غالبًا ما يكون من الضروري الهروب من أسماء الملفات والوسائط الأخرى التي تم تمريرها كمعلمات إلى الأوامر.كيف يمكنني أن أفعل هذا؟يُفضل أن يكون شيئًا يعمل على أنظمة تشغيل/أصداف متعددة ولكن بشكل خاص لـ bash.

أقوم حاليًا بما يلي، ولكنني متأكد من أنه يجب أن تكون هناك وظيفة مكتبة لهذا الغرض، أو على الأقل خيار أكثر أناقة/قوة/فعالية:

def sh_escape(s):
   return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")

os.system("cat %s | grep something | sort > %s" 
          % (sh_escape(in_filename), 
             sh_escape(out_filename)))

يحرر: لقد قبلت الإجابة البسيطة المتمثلة في استخدام علامات الاقتباس، ولا أعرف لماذا لم أفكر في ذلك؛أعتقد أنني أتيت من Windows حيث يتصرف "" و"" بشكل مختلف قليلاً.

فيما يتعلق بالأمان، أتفهم القلق، ولكن في هذه الحالة، أنا مهتم بحل سريع وسهل يوفره os.system()، ومصدر السلاسل إما لم يتم إنشاؤه من قبل المستخدم أو على الأقل تم إدخاله بواسطة مستخدم موثوق به (أنا).

هل كانت مفيدة؟

المحلول

هذا ما أستخدمه:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

ستقبل الصدفة دائمًا اسم الملف المقتبس وتزيل علامات الاقتباس المحيطة قبل تمريرها إلى البرنامج المعني.ومن الجدير بالذكر أن هذا يتجنب مشاكل أسماء الملفات التي تحتوي على مسافات أو أي نوع آخر من أحرف تعريف الصدفة السيئة.

تحديث:إذا كنت تستخدم Python 3.3 أو أحدث، فاستخدم shlex.quote بدلا من المتداول بنفسك.

نصائح أخرى

shlex.quote() يفعل ما تريد منذ بيثون 3.

(يستخدم pipes.quote لدعم كل من بيثون 2 و بيثون 3)

ربما لديك سبب محدد للاستخدام os.system().ولكن إذا لم يكن الأمر كذلك، فمن المحتمل أن تستخدم subprocess وحدة.يمكنك تحديد الأنابيب مباشرة وتجنب استخدام الصدفة.

ما يلي هو من بيب324:

Replacing shell pipe line
-------------------------

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

ربما subprocess.list2cmdline هل هي لقطة أفضل؟

لاحظ أن Pipes.quote معطل بالفعل في Python 2.5 وPython 3.1 وغير آمن للاستخدام - فهو لا يتعامل مع الوسائط ذات الطول الصفري.

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

يرى إصدار بايثون 7476;لقد تم إصلاحه في Python 2.6 و3.2 والأحدث.

أعتقد أن os.system يستدعي فقط أي واجهة أوامر تم تكوينها للمستخدم، لذلك لا أعتقد أنه يمكنك القيام بذلك بطريقة مستقلة عن النظام الأساسي.يمكن أن تكون قذيفة الأوامر الخاصة بي أي شيء بدءًا من bash أو emacs أو Ruby أو حتى quake3.بعض هذه البرامج لا تتوقع نوع الحجج التي تمررها إليهم، وحتى لو فعلوا ذلك، فليس هناك ما يضمن أنهم سيهربون بنفس الطريقة.

يلاحظ:هذه إجابة لـ Python 2.7.x.

بحسب ال مصدر, pipes.quote() هو وسيلة ل"اقتبس سلسلة بشكل موثوق كوسيطة واحدة لـ / بن / ش".(رغم أنه كذلك تم إهماله منذ الإصدار 2.7 وأخيراً تم الكشف عنها علنًا في Python 3.3 باسم shlex.quote() وظيفة.)

على من جهة أخرى, subprocess.list2cmdline() هو وسيلة ل"ترجمة سلسلة من الوسائط إلى سلسلة سطر أوامر، باستخدام نفس القواعد مثل وقت تشغيل MS C".

نحن هنا، الطريقة المستقلة للنظام الأساسي لاقتباس سلاسل أسطر الأوامر.

import sys
mswindows = (sys.platform == "win32")

if mswindows:
    from subprocess import list2cmdline
    quote_args = list2cmdline
else:
    # POSIX
    from pipes import quote

    def quote_args(seq):
        return ' '.join(quote(arg) for arg in seq)

الاستخدام:

# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)

الوظيفة التي أستخدمها هي:

def quote_argument(argument):
    return '"%s"' % (
        argument
        .replace('\\', '\\\\')
        .replace('"', '\\"')
        .replace('$', '\\$')
        .replace('`', '\\`')
    )

إنه:أقوم دائمًا بإحاطة الوسيطة بعلامات اقتباس مزدوجة، ثم أقتبس الشرطة المائلة العكسية للأحرف الوحيدة الخاصة داخل علامات الاقتباس المزدوجة.

إذا كنت تستخدم أمر النظام، فسأحاول إدراج ما يتم إدخاله في استدعاء os.system() في القائمة البيضاء.على سبيل المثال..

clean_user_input re.sub("[^a-zA-Z]", "", user_input)
os.system("ls %s" % (clean_user_input))

تعد وحدة العمليات الفرعية خيارًا أفضل، وأوصي بمحاولة تجنب استخدام أي شيء مثل os.system/subprocess حيثما أمكن ذلك.

الجواب الحقيقي هو:لا تستخدم os.system() في المقام الأول.يستخدم subprocess.call بدلاً من ذلك وتوفير الحجج التي لم يتم الهروب منها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top