Команда [
команда и анализируется как любая другая команда. Это означает, что в:
[ "$path" == ?*"@"?*":"?* ]
? * "@"? * ":"? *
рассматривается как глобус, поэтому он расширяется до списка файлов в текущем каталоге, которые соответствуют этому шаблону (просто например, *. txt
расширяется до списка файлов txt
в текущем каталоге).
Даже если бы вы написали это:
[ "$path" == '?*@?*:?*' ]
для предотвращения подстановки, это не сработает как оператор ==
(нестандартная версия =
) оператора [
] - это просто оператор равенства строк, а не оператор сопоставления с образцом.
Чтобы выполнить сопоставление с образцом, вы можете использовать ksh
-стайл [[x = образец]]
оператор сопоставления с образцом, который bash
и zsh
также поддерживает:
path="user@host:/home/user"
if [[ "$path" = ?*@?*:* ]]; then
some code
fi
Или, что еще лучше, используйте конструкцию POSIX / Bourne sh
case
:
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
, чтобы решить, является ли путь удаленным или нет. Если посмотреть на OpenSSH scp
код , путь будет удаленным, если он не начинается с :
и если он содержит :
без /
слева от него, и это не внутри [...]
(для адресов IPv6, таких как [:: 1]
. За исключением тех [...]
рассматриваются только в позиции хоста (в начале или после @
).Так, например, x:
, @:
- это удаленные пути (хотя, очевидно, часть пользователя и хоста пуста, что, скорее всего, не будет работать должным образом) и user @ [:: 1/64]: / x
( /
слева от :
, который не находится между [...]
) или [ foo @ bar: / path
- это локальные пути (:
находится внутри [...]
).
Было бы невозможно сопоставить это с одним оператором case POSIX . Чтобы сопоставить с одним регулярным выражением, было бы немного проще с регулярными выражениями, которые поддерживают такие операторы, как
perl
. zsh
и ksh93
поддерживают их ( zsh
с использованием библиотеки PCRE, ksh93
с использованием собственной реализации).
zsh
:
set -o rematchpcre
remote = '^ (?!:) (?: (?! \ [) [^ /:] * @)? (?: \ [(?: (?!]:) [^ /]) * \] | (?! \ [) [^ /:] *): '
if [[$ path = ~ $ remote] ]; затем
какой-нибудь код
fi
ksh93
:
remote = '(? P: ^ (?!:) (?: (?! \ [) [^ /:] * @)? (?: \ [(?: (?!]:) [^ /]) * \] | (?! \ [) [^ /:] *) :) '
если [[$ path = ~ $ remote]]; затем
какой-нибудь код
fi
(я не удивлюсь, если его можно упростить).