就這個問題而言,通過「csh」,我的意思是tcsh。爲csh引用一個字符串
我知道避免csh編程的標準建議。但是,有時需要與現有的csh代碼進行交互,然後可能需要引用csh的字符串。換句話說,問題是如何用csh語法表示一個任意的字節串。
以下csh_escape_arg函數是否正確?也就是說,是否存在一個字符串,如果它被添加到測試中的字符串列表中,會導致該測試失敗?如果有這樣的字符串,我該如何修復我的函數,以便所有字符串都通過測試?
import string
import subprocess
import unittest
# Safe unquoted
_safechars = frozenset(string.ascii_letters + string.digits + '@%_-+:,./')
def csh_escape_arg(str_):
"""Return a representation of str_ in csh.
Based on the standard library's pipes.quote
"""
for c in str_:
if c not in _safechars:
break
else:
if not str_:
return "''"
return str_
str_ = str_.replace("\\", "\\\\")
str_ = str_.replace("\n", "\\\n")
str_ = str_.replace("!", "\\!")
# use single quotes, and put single quotes into double quotes
# the string $'b is then quoted as '$'"'"'b'
return "'" + str_.replace("'", "'\"'\"'") + "'"
def csh_escape(args):
return " ".join(csh_escape_arg(arg) for arg in args)
def get_cmd_stdout(args, **kwargs):
child = subprocess.Popen(args, stdout=subprocess.PIPE, **kwargs)
stdout, stderr = child.communicate()
rc = child.returncode
if rc != 0:
raise Exception("Command failed with return code %d: %s:\n%s" % (rc, args, stderr))
else:
return stdout
class TestCsh(unittest.TestCase):
def test_hard_cases(self):
for angry_string in [
"\\!\n\"'`",
"\\\\!\n\"'`",
"=0",
]:
out = get_cmd_stdout(["tcsh", "-c", csh_escape(["echo", "-n", angry_string])])
self.assertEqual(out, angry_string)
unittest.main()
編輯代碼以解決Mark Armstrong指出的'='問題。 – 2013-03-09 18:32:53