ダックタイピングに関するネストの問題:
function f1 { echo $1; } #with argument
function f2 { N=$((0+1)); f$N "fff"; } #with dynamic name
望ましい結果:
function f2 { { echo $1; } "fff"; }
気づく申し訳ありません。実際のエンコーディングの問題で質問を修正しました。
問題を解決するには?
答え1
これはbashがすることではありません。これでもない支柱の拡張。だから私はあなたがここで何をしたいのか本当に知りたいです。
Bourneなどのシェルがどのように機能するかは、呼び出されたときにのみ実際に拡張される呼び出し可能な関数テーブルを介して機能します。したがって、解釈されると、f1;
関数はf1
「と言う、"以前のマクロではありません
したがって、あなたの希望する結果上記のコードとはほとんど関係がなく、本質的に同じではありません。関数には、スコープ{…}
付きステートメントのコレクションだけでなく、重要な固有のコンテキストとシンボルもあります。
したがって、あなたが望むことは、配偶者と配偶者がどのように機能するかを変えなければ不可能ですbash
。この時点で、シェルスクリプトよりTeXに近い他のプログラミング言語を使用しています。 (ところで、言語としてのTeXは…独創的ですが良い面では支配的ではありません。)
したがって、あなたの質問に示されているように、実際には変化を呼び出すときに関数リストでシンボル検索を実行するなど、プログラムは以前と同じように機能しませんf1;
。これにより、関数をオーバーライドする機能を利用するより複雑なスクリプトが中断される可能性があります。
私はこれが良いアイデアだとは思わないが、それはあなたの選択です。あなたは変化のないbashスクリプト用パーサー、シェル構文を理解できるパーサーいいえプログラムを実行します。原則として、残念ながら
POSIX シェル言語は、いくつかのレベルでコンパイラ構成の既存の概念に挑戦します。シェル言語は静的解析のために設計されていませんが、むしろ解析と拡張実行の組み合わせを可能にします。
特にここで強調することは次のとおりです。
語彙分析は、構文解析のコンテキストに依存します。と評価の文脈、
(Y. Régis-Gianas、N. Jeannerod、R. Treinen:Morbig:POSIXシェル用の静的パーサー)
これは一般的に言うと、できない静的解放。実行時に何が起こっているのかをf1
知る必要があります!f1
f2
POSIXシェルデザインいいえ一貫した型システムのようなものがない静的言語であるため、これを保証することはできません。alias f1=f3
実行時にプログラムの内容を変更するには、anを含む条件文が必要です! (この問題を解決するために使用できる他の多くのメカニズムがあります。)つまり、実行中の各ポイントで実際に「意味」が何であるかをf1
知ることができる唯一の時間であり、シェルの全体的な状態を知る必要があります(そして環境)。f2
f2
だからやりたいことをやってください。君は殻にならなければならない;bashを変更し、フックを介して特定のコンテンツを印刷(保存またはログ)できる拡張機能を追加する必要があります。
しかし、おそらく質問で要求されたものよりはるかに小さいものが欲しいかもしれません。おそらくシェルスクリプトを変更したくないかもしれませんが、いつでもシェルスクリプトから関数定義を印刷したいと思うかもしれません。これは次の方法でdeclare
行うことができます。declare -fp f1
答え2
これがあなたが追いかけているのでしょうか?
仕様を少し修正してみました。コマンドの2番目の引数に対応する関数は、関数foutとして環境にロードされます。スクリプトを実行すると
. duck.sh <string> <function number>
関数は親シェルの環境にロードされます。出力には、選択した関数と最初の引数(存在する場合)に基づいた出力が表示されます。
ファイルduck.sh:
#!/bin/bash
function f1 { echo $1; } #with argument
function f2 { f1; echo "here2 "$1; }
function f3 { f1; f2; echo "The Third "$1; }
function expandInner {
while [[ $toExpand != "" ]]; do
while read -r line; do
getInner $line
done <<< $toExpand
toExpand=$(grep -w -o 'f[0-9]' <<< $inner)
done
}
function getInner {
tmpString=$(typeset -f $1)
tmpString=$(echo $tmpString | awk 'BEGIN{RS="}"; FS="{"} {print $2}')
inner=${inner/${line}/${tmpString}}
}
if [ -z "$2" ] ; then
N=$((0+1))
else
N=$2
fi
inner=$(echo $(typeset -f f$N) | awk 'BEGIN{RS="}"; FS="{"} {print $2}')
toExpand=$(grep -w -o 'f[0-9]' <<< $inner)
expandInner
echo "function fout { $inner ; echo \"fff\"; }" | tee ~/.tmp; source ~/.tmp; rm ~/.tmp
fout $1