Подстановочный знак для пути к местоположению на удаленном хосте

В Bash мне нужно проверить, указывает ли путь, содержащийся в строке, на удаленное местоположение или нет. Не работает следующее: some code не выполняется. Кажется, что я что-то пропустил о том, как маскировки работают с командой test ( [ ), но я не могу понять, что. Страница руководства мне не помогает. Что я делаю неправильно и как я должен идти об этом вместо этого?

 path="user@host:/home/user" if [ "$path" == ?*"@"?*":"?* ]; then some code fi 

  • Какой тип движка регулярного выражения использует bash?
  • Ошибка с именем файла, содержащим круглые скобки
  • Могу ли я выбрать только один результат из шара bash?
  • Разделение аргумента командной строки bash
  • Перемещение и переименование сотен файлов .jpg, все имена 5003.jpg
  • su - -c 'll' other_user приводит к ошибке, как я могу запустить псевдоним другого пользователя?
  • Как я могу пропустить пустые файлы с sed?
  • Завершение бесконечного цикла
  • Скрипт для прокрутки папок с числовыми именами
  • Вызов cp из BASH и использование опции -u
  • Использование xargs с git
  • Значение «l» в «lrwxr-xr-x»?
  • One Solution collect form web for “Подстановочный знак для пути к местоположению на удаленном хосте”

    Команда [ command] является командой и анализируется как любая другая команда. Это означает, что в:

     [ "$path" == ?*"@"?*":"?* ] 

    « ?*"@"?*":"?* Принимается за глобус, поэтому он будет расширяться до списка файлов в текущем каталоге, который соответствует этому шаблону (так же, как *.txt расширяется до списка файлов txt в текущей каталог).

    Даже если вы написали это:

     [ "$path" == '?*@?*:?*' ] 

    для предотвращения глобуса, который не будет работать как оператор == (нестандартная версия = ) команды [ command] – это просто оператор равенства строк, а не соответствующий шаблону.

    Чтобы выполнить сопоставление с образцами, вы можете использовать ksh стиль [[ x = pattern ]] оператор сопоставления шаблонов, который также поддерживает bash и zsh :

     path="user@host:/home/user" if [[ "$path" = ?*@?*:* ]]; then some code fi 

    Или еще лучше, используйте конструкцию POSIX / Bourne sh :

     case $path in ?*@?*:*) some code esac 

    Таким образом, вам даже не нужно устанавливать bash , вы можете использовать стандартную sh для интерпретации вашего сценария.

    Обратите внимание, что user@host:/home/user также является допустимым локальным путем (попробуйте mkdir -p user@host:/home/user ), хотя с помощью scp вам нужно передать его как ./user@host:/home/user чтобы он не рассматривался как удаленный путь. Поэтому вы можете уточнить свой тест:

     case ${path%%@?*:*} in (*/* | "$path" | "") echo not a remote path;; (*) echo remote path;; esac 

    Так что ./x@y:z не обрабатывается как удаленный путь.

    Этого еще недостаточно, чтобы сделать то же самое, что и scp , чтобы решить, удалён или нет путь. Если посмотреть на scp код OpenSSH , путь будет удален, если он не начнется с : и если он содержит : с отсутствием / слева от него и который не находится внутри [...] (для адресов IPv6, таких как [::1] исключением того, что те [...] рассматриваются только в позиции хоста (в начале или после @ ). Так, например, x: @: – это удаленные пути (хотя, очевидно, пользователь и хост-часть пустые, вероятно, не будет работать должным образом) и user@[::1/64]:/x ( / left to : не находится между [...] ) или [foo@bar:/path – это локальные пути ( : находится внутри [...] ).

    Согласование этого с одним заявлением case POSIX было бы невозможным. Чтобы соответствовать одному регулярному выражению, было бы немного легче с регулярными выражениями, которые поддерживают внешний вид операторов, таких как perl . zsh и ksh93 поддерживают те ( zsh используя библиотеку PCRE, ksh93 используя собственную реализацию).

    • zsh :

       set -o rematchpcre remote='^(?!:)(?:(?!\[)[^/:]*@)?(?:\[(?:(?!]:)[^/])*\]|(?!\[)[^/:]*):' if [[ $path =~ $remote ]]; then some code fi 
    • ksh93 :

       remote='(?P:^(?!:)(?:(?!\[)[^/:]*@)?(?:\[(?:(?!]:)[^/])*\]|(?!\[)[^/:]*):)' if [[ $path =~ $remote ]]; then some code fi 

    (Я не удивлюсь, если это будет упрощено).

    Linux и Unix - лучшая ОС в мире.