[ACCEPTED]-Python module to shellquote/unshellquote?-quoting
Looks like
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"'
gets me far enough.
0
pipes.quote
is now shlex.quote
in python 3.
It is easy enough 2 to use that piece of code.
https://github.com/python/cpython/blob/master/Lib/shlex.py#L281
That version handles 1 zero-length argument correctly.
To unquote, try shlex.split()
0
I'm pretty sure that pipes.quote is broken, and 3 should not be used, because it does not 2 handle zero-length arguments correctly:
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
I 1 believe the result should be something like
mycommand arg1 '' arg3
For shell quoting, this works: I've rigorously 4 tested it on Posix. [I'm assuming that 3 the list2cmdline
function supplied by Python works as 2 advertised on 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 ])
The tests are here, if 1 anyone cares.
The standard library module subprocess has 4 the list2cmdline function which does this, albeit 3 according to Microsoft rules so I am not sure how reliable 2 it works in Unix-like environments for more 1 complicated command lines.
The quote
function is available for quite some 4 time (Python 2.7?) -- the major drawback 3 is it moved from pipe
module to shlex
between 3.2 2 and 3.3.
You have to be prepared to handle 1 both cases while importing that function:
try:
from shlex import quote
except ImportError:
from pipes import quote
You should never have to shell quote. The 6 correct way to do a command is to not do 5 shell quoting and instead use subprocess.call or subprocess.Popen, and 4 pass a list of unquoted arguments. This 3 is immune to shell expansion.
i.e.
subprocess.Popen(['echo', '"', '$foo'], shell=False)
If you 2 want to unquote shell quoted data, you can 1 use shlex.shlex like this:
list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.