#! /usr/bin/env python
######################################################################
# Written by Kevin L. Sitze on 2006-12-03
# This code may be used pursuant to the MIT License.
######################################################################
import re
__all__ = ( 'quote', )
_bash_reserved_words = {
'case' : True,
'coproc' : True,
'do' : True,
'done' : True,
'elif' : True,
'else' : True,
'esac' : True,
'fi' : True,
'for' : True,
'function' : True,
'if' : True,
'in' : True,
'select' : True,
'then' : True,
'until' : True,
'while' : True,
'time' : True
}
####
# _quote_re1 escapes double-quoted special characters.
# _quote_re2 escapes unquoted special characters.
_quote_re1 = re.compile( r"([\!\"\$\\\`])" )
_quote_re2 = re.compile( r"([\t\ \!\"\#\$\&\'\(\)\*\:\;\<\>\?\@\[\\\]\^\`\{\|\}\~])" )
def quote( *args ):
"""Combine the arguments into a single string and escape any and
all shell special characters or (reserved) words. The shortest
possible string (correctly quoted suited to pass to a bash shell)
is returned.
"""
s = "".join( args )
if _bash_reserved_words.has_key( s ):
return "\\" + s
elif s.find( '\'' ) >= 0:
s1 = '"' + _quote_re1.sub( r"\\\1", s ) + '"'
else:
s1 = "'" + s + "'"
s2 = _quote_re2.sub( r"\\\1", s )
if len( s1 ) <= len( s2 ):
return s1
else:
return s2
if __name__ == '__main__':
import sys
import traceback
from types import FloatType, ComplexType
def assertEquals( exp, got ):
"""assertEquals( exp, got )
Two objects test as "equal" if:
* they are the same object as tested by the 'is' operator.
* either object is a float or complex number and the absolute
value of the difference between the two is less than 1e-8.
* applying the equals operator ('==') returns True.
"""
if exp is got:
r = True
elif ( type( exp ) in ( FloatType, ComplexType ) or
type( got ) in ( FloatType, ComplexType ) ):
r = abs( exp - got ) < 1e-8
else:
r = ( exp == got )
if not r:
print >>sys.stderr, "Error: expected <%s> but got <%s>" % ( repr( exp ), repr( got ) )
traceback.print_stack()
for word in _bash_reserved_words:
assertEquals( "\\" + word, quote( word ) )
for char in ( '\t',
' ', '!', '"', '#',
'$', '&', "'", '(',
')', '*', ':', ';',
'<', '>', '?', '@',
'[', ']', '^', '`',
'{', '|', '}', '~' ):
assertEquals( "\\" + char, quote( char ) )
assertEquals( "'this is a simple path with spaces'",
quote( 'this is a simple path with spaces' ) )
assertEquals( "don\\'t", quote( "don't" ) )
assertEquals( '"don\'t do it"', quote( "don't do it" ) )