Создайте экранированный путь POSIX в macOS - PullRequest
0 голосов
/ 27 марта 2019

Мне нужно создать строку из полного пути POSIX (начиная с корня), чтобы она могла быть вставлена ​​непосредственно в оболочку Unix, например bash, например, в Terminal.app, безнеобходимость заключать в кавычки путь.

(Я на самом деле не передаю строку в оболочку, а вместо этого нуждаюсь в ней для передачи в другую программу. Эта программа ожидает путь только в форме, котораявы получаете, когда вы перетаскиваете файл в Terminal.app.)

. Для этого мне нужно экранировать хотя бы любые пробелы в строке, добавляя перед ними обратную косую черту.И еще несколько символов.

Например, этот путь:

/directory/-as"<>' *+

Экранируется следующим образом:

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

Какой безопасный алгоритм для этого преобразования?Я мог бы экранировать каждый символ, но это было бы излишним.

Кажется, что для этого не существует фреймворковой функции, поэтому мне нужно будет выполнить замену строковыми операциями.

Чтобы быть консервативным (для самых популярных оболочек), а также избегать явно ненужных выходов, какой набор символов следует избегать?

Ответы [ 2 ]

0 голосов
/ 07 апреля 2019

Для записи, 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;
}
0 голосов
/ 27 марта 2019

Лучше поместить все это в одинарные кавычки, а не добавлять обратную косую черту к отдельным персонажам;тогда единственный символ, который вам нужно экранировать, - это одиночная кавычка, присутствующая внутри строки.

Реализация стандартной библиотеки *1003* в Python, приведенная в качестве примера, которая может быть легко переопределена на любом другом языке, имеющемтолько основные примитивы, читается следующим образом:

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("'", "'\"'\"'") + "'"

То есть, общий алгоритм выглядит следующим образом:

  • Пустая строка становится '' (пара литераловодиночные кавычки).
  • Строка, которая, как известно, безопасна (хотя безопаснее вообще не пытаться реализовать кодовый путь для этого, особенно, поскольку оболочки часто реализуют свои собственные расширения синтаксиса в неопределенном пространстве)испускается голым / без кавычек.
  • В противном случае, добавьте ', испустите вашу входную строку со всеми ' s, замененными литеральной строкой '"'"', а затем добавьте окончательный '.

Вот и все.Вам не нужно избегать обратной косой черты (они буквально заключены в одинарные кавычки), новых строк (аналогично) или чего-либо еще.

...