在macOS中创建脱壳的POSIX路径

时间:2019-03-27 15:56:31

标签: bash macos cocoa posix core-foundation

我需要从完整的POSIX路径(从根开始)创建一个字符串,以便可以 直接将其粘贴到bash之类的Unix shell中,例如Terminal.app中,而无需在路径两边加上引号。

(我实际上并没有将字符串传递给shell,而是需要将其传递给另一个程序。该程序期望将路径拖放到{{1 }}。)

为此,我需要至少在字符串中转义任何空格,方法是在它们前面加上反斜杠。还有一些其他字符。

例如,此路径:

Terminal.app

将按照以下说明进行转义:

/directory/-as"<>' *+

执行该转换的安全算法是什么?我可以逃避每个角色,但这太过分了。

似乎没有框架函数可以执行此操作,因此我需要用字符串操作进行替换。

为保守起见(对于最流行的外壳),同时还避免了明显的不必要的转义,应转义哪些字符集?

2 个答案:

答案 0 :(得分:0)

最好将整个内容用单引号引起来,而不是在单个字符上加上反斜杠;那么您唯一需要转义的字符就是字符串中的单引号。

作为示例提供的Python standard library's implementation可以很容易地以仅具有基本基元的任何其他语言重新实现,其内容如下:

def quote(s):
    """Return a shell-escaped version of the string *s*."""
    if not s:
        return "''"
    if _find_unsafe(s) is None:
        return s

    # use single quotes, and put single quotes into double quotes
    # the string $'b is then quoted as '$'"'"'b'
    return "'" + s.replace("'", "'\"'\"'") + "'"

也就是说,一般算法如下:

  • 一个空字符串变成''(一对文字单引号)。
  • 一个已知是安全的字符串(尽管完全不尝试为此实现代码路径是最安全的,尤其是由于shell经常在未定义的空间中实现其自身的语法扩展)可以被裸露/不加引号。
  • 否则,请在'之前添加,发出输入字符串,并用文字字符串'替换所有'"'"',然后附加最后的'

就是这样。您不需要转义反斜杠(它们在单引号内是字面量),换行符(同样)或其他任何东西。

答案 1 :(得分:0)

作为记录,Terminal.app在将文件名放入其窗口时转义了以下非控制ASCII字符:

  

空格

     

!“ ##%&'()*,:; <=>?[]`{|}〜

这些都无法逃脱:

  

控制代码(00-1F和7F)

     

字母数字

     

+-。@ ^ _

这是执行替换的代码:

NSString* shellPathFromPOSIXPath (NSString *path)
{
    static NSRegularExpression *regex = nil;
    if (!regex) {
        NSString *pattern =
          @"([ !\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\,\\:\\;\\<\\=\\>\\?\\[\\]\\`\\{\\|\\}\\~])";
        regex =
          [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
    }
    NSString *result =
      [regex stringByReplacingMatchesInString:path
                                      options:0
                                        range:NSMakeRange(0, path.length)
                                 withTemplate:@"\\\\$1"];
    return result;
}