QA@IT

glob で最初にマッチしたものだけ取り出したい

2063 PV

echo ${^fpath}/vcs_info(N)echo ${^path}/zsh(N-*) のようにすると path からファイルや実行ファイルを探せます。
vcs_info のように1個しかマッチしない場合は良いのですが、 zsh のように複数マッチする場合でも、最初だけ取り出したいです。

Glob Qualifiers の [beg,[end]] を使って

echo ${^path}/zsh(N-*[1])

としてみても ${^path} の RC_EXPAND_PARAM で分解された後のそれぞれのディレクトリに対して Glob Qualifiers が適用されるため、 /usr/bin/zsh と /bin/zsh の両方が出てきてしまいます。

${(@)...[1]} を使ってみれば良いかと思って

echo ${(@)${${^path}/zsh(N-*)}[1]}

としてみてもうまく glob されずに

echo $path[1]

と同じ結果になっただけでした。

回答

シェル変数を介すのでは駄目ですか。

$ echo ${^path}/zsh(N-*)
/bin/zsh /usr/bin/zsh /usr/bin/X11/zsh
$ set - ${^path}/zsh(N-*); echo "$1"
/bin/zsh
$ set -A zsh ${^path}/zsh(N-*); echo "${zsh[1]}" # 必要ならさらに unset zsh
/bin/zsh

実行ファイルを探すのには組込みコマンド whence が適していますが、これは $PATH から探すので、$path から探したいということであれば、次のようにすれば実現できます。

$ PATH="$path" whence -p zsh
/bin/zsh
編集 履歴 (2)
  • [[ -x $... ]] のような埋め込みに使えないので、出来れば避けたいですが、用途によってはシェル変数に一度入れてから、というのがわかりやすいし、一番無難そうです。 -
  • そんな場合は [[ -x ... ]] の代わりに `whence -p zsh >/dev/null && echo "zsh found"` とか `whence -p zsh >/dev/null || echo "zsh not found"` のような感じで充分ではないでしょうか。 -

外部コマンド(sedとかheadとか)を使ったら負けですよねぇ

$ print -l ${^path}/ls(N-*) | sed 1q
/opt/local/libexec/gnubin/ls

編集 履歴 (0)
  • zsh 内部だけで出来ることは、出来るだけ外部コマンドは呼びたくないので、負けですねぇ。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。