パラメータ置換のデフォルト値を要素の配列に設定するには?

パラメータ置換のデフォルト値を要素の配列に設定するには?

私はzshを使用しており、次の機能があります。

function timer-raw() {
    # Just think `loop fsayd` is `echo hi` for the purposes of this question.
    eval "sleep $((($1)*60))" && eval ${(q+@)@[2,-1]:-loop fsayd}
}

timer-rawの最初のパラメータは、待機する時間(分)を示します。残りのパラメータ(存在する場合)は、evalコマンドラインに入力したように待機後に編集されます。

timer 3 echo sth
# After 3 minutes, echoes `sth`.

ただし、引数が指定されなくなった場合は、基本コマンドを実行したいと思いますloop fsayd

timer 4
# runs `loop fsayd` after 4 minutes

問題は、2つの単語に置き換えたいのですが、loop fsayd方法がわからないということです。また、これらのバリエーションを試しましたが、うまくいきません。

"${(q+@)${@[2,-1]:-loop fsayd}}"
"${(q@)${(q@)=@[2,-1]:-loop fsayd}}"
"${(qq@)=@[2,-1]:-loop fsayd}"

「動作しない」とは、単純な操作が失敗したか、正しい数の入力引数を返さないことをtimer 0意味しますcommand not foundtimer 0 ff hi 'man hi jk k'( ff() echo "$#")

注:を使用したくありませんtest -z "${@[2,-1]}"

答え1

ハハ、見つけました:

function timer-raw() {
    eval "sleep $((($1)*60))" && eval ${(q+@)@[2,-1]:-${(z)/#/loop fsayd}}
}

${name/pattern/repl}これは、空の文字列である ""(nothing)という名前の存在しない変数の内容を置き換えます()。#単語分割(オプション)の実行中に(空)文字列(パターン)の先頭をループfsaydに置き換えます(z)。 .... :D

答え2

変数にデフォルト値を定義できる場合は、次のことができる必要があります。

function timer-raw() {
    defs=( loop fsayd )
    eval "sleep $((($1)*60))" && eval ${(q+@)@[2,-1]:-$defs}
}

個人的に私はevalを使用しませんが、次のことを行います。

function timer-raw() {
    defs=( loop fsayd )
    sleep ${1}m && ${@[2,-1]:-$defs}
}

関連情報