在macOS中创建一个shell转义的POSIX路径

问题描述 投票:0回答:2

我需要从一个完整的POSIX路径创建一个字符串(从根开始),这样它就可以直接粘贴到像bash这样的Unix shell中,例如在Terminal.app,不需要在路径周围引用。

(我实际上并没有将字符串传递给shell,而是需要将它传递给另一个程序。该程序只需要将文件拖到Terminal.app时获得的路径。)

为此,我需要至少在字符串中的任何空格中进行转义,方法是在前面加上反斜杠。还有一些角色。

例如,这条路径:

/directory/-as"<>' *+

将被转义如下:

/directory/-as\"\<\>\'\ \*+

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

似乎没有用于执行此操作的框架功能,因此我需要使用字符串操作进行替换。

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

bash macos cocoa posix core-foundation
2个回答
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通常在未定义的空间中实现它们自己的语法扩展)可以是裸/不引用的。
  • 否则,前置一个',发出你的输入字符串,所有's替换为文字字符串'"'"',然后附加一个最终的'

而已。您不需要转义反斜杠(它们在单引号内是字面值),换行符(同样)或其他任何内容。


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;
}
© www.soinside.com 2019 - 2024. All rights reserved.