Skip to content

Instantly share code, notes, and snippets.

@chaimleib
Created May 25, 2022 06:11
Show Gist options
  • Save chaimleib/ec842f571c5aab85f6c9b045c458e973 to your computer and use it in GitHub Desktop.
Save chaimleib/ec842f571c5aab85f6c9b045c458e973 to your computer and use it in GitHub Desktop.
def shell_escape(s, quote_empty=True):
if quote_empty and s == '':
return "''"
squot = False
dquot = False
dquot_special = False
special = False
escaped = []
for c in s:
if c == "'":
squot = True
escaped.append("\\")
escaped.append(c)
elif c == '"':
dquot = True
dquot_special = True
escaped.append("\\")
escaped.append(c)
elif c in '$`\\':
special = True
dquot_special = True
escaped.append("\\")
escaped.append(c)
elif c in '{}[]()*~|;!#& =?<>':
special = True
escaped.append("\\")
escaped.append(c)
else:
escaped.append(c)
if not special:
if not squot and not dquot:
return s
if squot and not dquot:
return '"' + s + '"' if len(escaped) >= len(s) + 2 else ''.join(escaped)
if dquot and not squot:
return "'" + s + "'" if len(escaped) >= len(s) + 2 else ''.join(escaped)
return "\\'".join(shell_escape(word, False) for word in s.split("'"))
prefer_quotes = len(escaped) >= len(s) + 2
if not squot and prefer_quotes:
return "'" + s + "'"
elif not dquot_special and prefer_quotes:
return '"' + s + '"'
else:
return ''.join(escaped)
if __name__ == '__main__':
cases = [
'',
' ',
' ',
' ',
'hello',
'hello world',
'hello world!',
"I'm here?",
"I'm here.",
"I'm (not) spending any $$~",
'He said, "This is a quote."',
'Try [some] {braces}',
'$(one command \'quote\')+`and another`'
]
for case in cases:
print(shell_escape(case))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment