2013-03-07 10 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이 지적한 '='문제를 수정하는 코드를 편집했습니다. –

답변

2

1) tcsh의 경우 디렉토리 스택 대체를 방지하려면 "="인용 부호가 필요합니다. 2) 나는 당신의 알고리즘이 쌍 따옴표가없는 큰 따옴표가있는 문자열에도 문제가 있다고 생각합니다. 3) 대안은 문자열이 대체 대상이되지 않도록 대상 스크립트를 작성하는 것입니다. 파일에 캐릭터 라인을 기입 한 다음 필요에 의해 예를 들어 스크립트는

set a = `cat file` 

처럼 변수에 파일에서 문자열을 읽고 다음 필요에 따라 변수를 사용합니다.

+0

감사합니다. =. 그 문자를 "안전한"목록에서 제거하면 문제를 해결할 수 있습니다. 쌍 따옴표가없는 큰 따옴표에 관해서는 예제를 줄 수 있습니까? (파이썬 구문으로) '' ',' "foo", "foo"와 같은 문자열은 이미 내 질문에 테스트를 통과합니다. –

+0

두 번째로 괜찮은 것 같아요. –