リモートホストのロケーションパスのワイルドカード

リモートホストのロケーションパスのワイルドカード

Bashでは、文字列に含まれるパスがリモートの場所を指していることを確認する必要があります。以下は効果がありませんsome code。実行されません。test( )コマンドでワイルドカードがどのように[機能するかについていくつかの情報が欠けているようですが、何がわかりません。マニュアルページは私には役に立ちません。私は何が間違っていましたか?この問題をどのように解決するのですか?

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

答え1

コマンド[はコマンドであり、他のコマンドに解析されます。これは次のことを意味します。

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

globとして扱われるので、?*"@"?*":"?*パターンと一致する現在のディレクトリのファイルリストに展開されます(現在のディレクトリのファイルリストに展開されるのと同じ*.txt)。txt

次のように書いても:

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

ワイルドカードを防ぐために、コマンドの==演算子(非標準バージョン)がパターン一致演算子ではなく文字列同等演算子であるため、これは機能しません。=[

パターンマッチングを実行するには、以下をサポートするksh-style[[ x = pattern ]]パターンマッチング演算子を使用できます。bashzsh

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

あるいは、より良い方法はPOSIX / Bournesh case設定を使用することです。

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

これによりインストールする必要がなく、bashシステム標準を使用してshスクリプトを解釈できます。

これもuser@host:/home/user有効です。地元のpath(try)を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パスがリモートであることを確認するのと同じことを行うにはまだ十分ではありません。見ているOpenSSHscpコード、左側にnoがあり、下にないパスが含まれていて、開始せずに含まれて:いる場合、パスはリモートパスです。もちろん、ユーザーとホスト部分は空であるため、正しく機能しない可能性があります。:(中間に残らない)またはローカルパス(内部)。/[...][::1][...]@x:@:user@[::1/64]:/x/:[...][foo@bar:/path:[...]

これをPOSIXcase文と一致させることは不可能です。正規表現を一致させるには、などのラップアラウンド演算子をサポートする正規表現を使用する方がやや簡単ですperl。これをサポートします(zshPCREライブラリの使用、自己実装の使用)。ksh93zshksh93

  • zsh:

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

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

(単純化できれば驚かないでしょう)。

関連情報