私の会社が現在使用しているいくつかの複雑なスクリプトで実装される bash ロギング ライブラリを作成しました。ログ呼び出しを行うときに、呼び出し元のスクリプトのスクリプト ファイル名 (${BASH_SOURCE}) と行番号 (${LINENO}) を提供することに行き詰まりました。ただし、これら 2 つの変数をパラメーターとして渡すために、ユーザーや実装スクリプトに依存する必要はありませんでした。これが C/C++ の場合は、"__FILE__" と "__LINE__" をパラメーター リストの先頭に追加するマクロを作成します。
私はついにこの部分を機能させることができました。概念実証として、大幅に簡略化した要約を次に示します。
ロギング ライブラリは次のとおりです。
# log.sh
LOG="eval _log \${BASH_SOURCE} \${LINENO}"
_log () {
_BASH_SOURCE=`basename "${1}"` && shift
_LINENO=${1} && shift
echo "(${_BASH_SOURCE}:${_LINENO}) $@"
}
そして、実装テスト スクリプト:
# MyTest.sh
. ./log.sh
${LOG} "This is a log message"
# (test.sh:5) This is a log message
これはかなりうまく機能します (そして、最初は機能することにわくわくしました)。ただし、これには 1 つの明らかな問題があります。引用符と eval の間の相互作用です。私が電話をかける場合:
${LOG} "I'm thrilled that I got this working"
# ./test.sh: eval: line 5: unexected EOF while looking for matching `''
# ./test.sh: eval: line 6: syntax error: unexpected end of file
今、私はこれがなぜ起こっているのかを理解していると信じています。引用符で囲まれたパラメーターは、eval に渡されるときにそのまま保持されますが、その時点で、コンテンツは結果のコマンド文字列にそのまま配置されます。エスケープを行うことでこれを修正できることはわかっています。ただし、実装するスクリプトにこれを強制する必要はありません。この「評価マクロ」機能を実装する前に、ユーザーに「_log」を直接呼び出してもらい、オプションで「${LINENO}」を渡せるようにしました。この実装では、上記の失敗した呼び出し (引用文のみ) は問題なく機能しました。
最も基本的なレベルでは、スクリプトが[ログ関数/マクロ] 「特殊文字を使用してログに記録する文字列」を呼び出し、結果のログ メッセージに呼び出し元のスクリプトのファイル名と行番号を含めることができるようにするだけです。ログメッセージが続きます。可能であれば、私は非常に近いと思いますが、別のアプローチが必要な見落としがある場合は、それも受け入れます. ユーザーがすべてのメッセージをエスケープするように強制することはできません。これにより、ユーザーはこのライブラリを使用しなくなる可能性があります。これは非常に問題であるため、解決策が見つからない場合は、古い機能に戻る可能性があります (関数パラメーターとして ${LINENO} を渡す必要がありましたが、これはそれほど邪魔になりませんでした)。
TLDR :引用符で囲まれたパラメーター内の特殊文字をエスケープせずに尊重するように eval を取得する方法はありますか?