2013-03-07 62 views
0

就這個問題而言,通過「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() 
+0

編輯代碼以解決Mark Armstrong指出的'='問題。 – 2013-03-09 18:32:53

回答

2

1)對於tcsh,您還需要引用「=」來防止目錄堆棧替換。 2)我認爲你的算法也會遇到一個帶有不成對的雙引號的字符串問題。 3)另一種方法是編寫你的目標腳本,使得字符串不會被替換。比如通過寫你的字符串到一個文件,然後讓你的腳本從文件中讀取字符串到一個變量,像

set a = `cat file` 

,然後使用該變量需要。

+0

謝謝re =。這可以通過從「安全」列表中刪除該字符來解決。至於不成對的雙引號,你能舉個例子嗎?像(在Python語法中)'''',''foo'和'foo''這些字符串都已通過我的問題的測試。 – 2013-03-08 22:30:08

+0

第二次認爲它看起來很好 – 2013-03-08 23:14:56

相關問題