سؤال

هذا السؤال لديه بالفعل إجابة هنا:

هل هناك أي شيء في مكتبة Python Standard التي ستتحليل / سلاسل غير مشروطة للاستخدام في أوامر Shell؟ أنا أبحث عن python التناظرية إلى بيرل String::ShellQuote::shell_quote:

$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool

والأهم من ذلك، شيء سيعمل في الاتجاه المعاكس (خذ سلسلة وتحلله في قائمة).

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

المحلول

pipes.quote هو الآن shlex.quote في بيثون 3. من السهل بما فيه الكفاية لاستخدام هذه القطعة من التعليمات البرمجية.

https://github.com/python/cpython/blob/master/lib/shlex.py#l281.

هذا الإصدار يتعامل مع وسيطة طول الصفر بشكل صحيح.

نصائح أخرى

يشبه

try:  # py3
    from shlex import quote
except ImportError:  # py2
    from pipes import quote

quote("hello stack overflow's quite cool")
>>> '"hello stack overflow\'s quite cool"'

يجعلني بعيدا بما فيه الكفاية.

أنا متأكد من أن الأنابيب. يتم كسر الأنابيب، ولا ينبغي استخدامها، لأنه لا يتعامل مع حجج الطول الصفر بشكل صحيح:

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

أعتقد أن النتيجة يجب أن تكون شيء مثل

mycommand arg1 '' arg3

للاضطرار قذيفة، هذا يعمل: لقد اختبرته بدقة على posix. [أفترض أن list2cmdline الوظيفة المقدمة من Python يعمل كما هو معلن على Windows

# shell.py
import os
if os.name == 'nt':
    from subprocess import list2cmdline

    def quote(arg):
        return list2cmdline([arg])[0]
else:
    import re
    _quote_pos = re.compile('(?=[^-0-9a-zA-Z_./\n])')

    def quote(arg):
        r"""
        >>> quote('\t')
        '\\\t'
        >>> quote('foo bar')
        'foo\\ bar'
        """
        # This is the logic emacs uses
        if arg:
            return _quote_pos.sub('\\\\', arg).replace('\n',"'\n'")
        else:
            return "''"

    def list2cmdline(args):
        return ' '.join([ quote(a) for a in args ])

الاختبارات هي هنا, ، إذا كان أي شخص يهتم.

لإلغاء تحديد، حاول shlex.split()

يجب ألا تضطر أبدا إلى القشرة. الطريقة الصحيحة للقيام بأمر غير أن لا تفعل قذيفة اقتباس واستخدامها بدلا من ذلك subprocess.call. أو subprocess.popen., ، وتمرير قائمة الحجج غير المسبقة. هذا محصن من توسيع شل.

بمعنى آخر

subprocess.Popen(['echo', '"', '$foo'], shell=False)

إذا كنت ترغب في إلغاء تغيير بيانات القذيفة، فيمكنك استخدامها shlex.shlex. مثله:

list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))

تحتوي وحدة المكتبة الفرعية المكتبة المعيارية على وظيفة List2cmdline التي تفعل هذا، وإن كان وفقا ل قواعد مايكروسوفت لذلك أنا لست متأكدا من مدى موثوقية أنه يعمل في بيئات مثل UNIX لمزيد من خطوط الأوامر المعقدة.

ال quoteالوظيفة متاحة لبعض الوقت (بيثون 2.7؟) - العيب الرئيسي هو انتقلت من pipe الوحدة إلى shlex بين 3.2 و 3.3.

يجب أن تكون مستعدا للتعامل مع كلتا الحالتين أثناء استيراد هذه الوظيفة:

try:
    from shlex import quote
except ImportError:
    from pipes import quote
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top