単語の一部内でグローバルエイリアスを強制的に拡張します。

単語の一部内でグローバルエイリアスを強制的に拡張します。

/tmp/foo/bar.sh次のスクリプトがいくつかあります/tmp/foo/baz.sh

# /tmp/foo/bar.sh

alias -g __FILE__='${(%):-%x}'
alias -g __DIR__='${${(%):-%x}%/*}'

printf "sourcing %s\n" __FILE__
printf "about to source %s/baz.sh\n" __DIR__

. /tmp/foo/baz.sh

. $( printf "%s/baz.sh" __DIR__ ) # succeeds
. __DIR__"/baz.sh"                  # fails
# /tmp/foo/baz.sh

printf "sourcing %s\n" __FILE__

最初のスクリプトは/tmp/foo/bar.shいくつかを定義します。グローバル-g)拡張する必要がある注文としてのエイリアス(最初の近似! )を現在のスクリプトの(呼び出し)パスに追加し、ディレクトリを含めます。次に、これらのエイリアスを複数のコマンドのprintf引数として使用します。最後に、/tmp/foo/baz.sh3つの方法で2番目のスクリプトをインポートします。

  1. 2番目のスクリプトのリテラルパスを使用します。
  2. __DIR__printfコマンド置換によって間接的にエイリアスを使用します。
  3. エイリアスを直接使用してください__DIR__

最初のスクリプトを受け取ったときに得たものは次のとおりです。

% (/usr/bin/env -i zsh -fc '. /tmp/foo/bar.sh')
sourcing /tmp/foo/bar.sh
about to source /tmp/foo/baz.sh
sourcing /tmp/foo/baz.sh
sourcing /tmp/foo/baz.sh
/tmp/foo/bar.sh:.:11: no such file or directory: __DIR__/baz.sh

(歌とダンスはできるだけ簡単な設定で/usr/bin/envやろうとします。)/tmp/foo/bar.sh

__DIR__すぐに従うと/baz.shエイリアスとして認識されないようです。この形式は$( printf "%s/baz.sh" __DIR__ )この問題を解決しますが、最初にエイリアスを使用すると、長さと複雑さが大幅に向上します。

エイリアスを使用して2番目の文字列へのパスを作成するより便利な方法はありますか__DIR__

より一般的には、特定の文字シーケンスをエイリアスとして扱う必要があることをパーサに知らせる一般的な「文法トリック」はありますか?私の希望は、このようなグローバルエイリアスを次のようにすることです。シンプル(つまり、1行、パラメータなしなど)Cプリプロセッサマクロ。心に浮かぶ「構文トリック」の例は次のとおりです(どちらも機能しません)。

. {__DIR__}/baz.sh
. __DIR__"/baz.sh"

答え1

1つの文字列を単一の追加文字を持つ別の文字列に置き換えることができる関数があります。

__FILE__='${(%):-%x}'
__DIR__='${${(%):-%x}%/*}'
. $__DIR__/baz.sh

実際に変数を定義したくない場合の別のアプローチは、単語の先頭のチルダ文字の後にのみ拡張される名前付きディレクトリを定義することです。これはあなたの例ではうまくいきますが、あなたが望むすべてのケースで一般化されるわけではありません。

hash -d __FILE__='${(%):-%x}'
hash -d __DIR__='${${(%):-%x}%/*}'
. ~__DIR__/baz.sh

答え2

さて、以下のような適切な解決策を見つけました。

# /tmp/foo/bar.sh

alias -g __FILE__='echo "${(%):-%x}"'
alias -g __DIR__='echo "${${(%):-%x}%/*}"'

printf "sourcing %s\n" $(__FILE__)
printf "about to source %s/baz.sh\n" $(__DIR__)

. $(__DIR__)/baz.sh               # succeeds

関連情報