【发布时间】:2019-03-27 15:56:31
【问题描述】:
我需要从完整的 POSIX 路径(从根目录开始)创建一个字符串,以便将它可以直接粘贴到像 bash 这样的 Unix shell 中,例如在Terminal.app 中,不需要在路径周围加上引号。
(我实际上并没有将字符串传递给 shell,而是需要它来将其传递给另一个程序。该程序期望路径的格式与您将文件拖入 Terminal.app 时所获得的形式相同.)
为此,我需要通过在字符串中添加反斜杠来转义至少所有空格。还有更多字符。
例如这条路径:
/directory/-as"<>' *+
转义如下:
/directory/-as\"\<\>\'\ \*+
执行该转换的安全算法是什么?我可以转义每一个字符,但这太过分了。
似乎没有框架函数可以做到这一点,所以我需要用字符串操作替换。
为了保守(对于最流行的 shell),在避免明显不必要的转义的同时,应该转义哪些字符集?
【问题讨论】:
-
如果这是一个快速的问题,应该这样标记。如何在 in bash 中执行此操作的最佳答案是要求 shell 本身为您进行转义:
printf '%q\n' "$name" -
也就是说,如果您想要一个简短、易读且实用的参考实现,the Python 3.x
shlex.quoteimplementation 在这里做得很好。需要注意的是,它不能保证输出只是 ASCII 可读/可见字符;如果您尝试使用制表符/换行符/BELs/等引用某些内容,您将得到制表符/换行符/BELs/等,只是在引号中,因此符合 POSIX 的 shell 会将它们视为文字。 -
...当然,您也可以将 shell 作为子进程分叉。
execlp("bash", "bash", "-c", "printf '%q' \"$1\"", "_", myStringVar, NULL)是它在 C 中的样子(输出写入标准输出并能够从中捕获),这将为您提供仅使用可打印 ASCII 字符的 7 位干净结果(尽管不能保证所有人都支持POSIX shell;$''是一种 ksh-and-bash-ism,可能会在稍后的标准中出现,但目前还没有)。 -
如果你想要万无一失,这也取决于你真正要粘贴的内容。考虑文件名“-rq”。完全合法,不需要任何转义,但粘贴到某些命令行中确实很糟糕(前缀为“./”或“.\\”以确保安全,具体取决于您的操作系统)
-
如果您要粘贴到 shell 中,您需要担心的是 shell 解析器,而不是您的目标程序,因此 (1) 通配符,(2) 空格 (3) 重定向和进程控制, (4) 引用和转义。即,'“*?();|$ 等,如果您要传递到 argv 数组中的另一个应用程序,则不需要转义,除非它很麻烦。
标签: bash macos cocoa posix core-foundation