はい、一般的な解決策です。次のbash関数には2k
引数が必要です。各ペアは、プレースホルダーと置換で構成されます。文字列を適切に引用して関数に渡すのはあなた次第です。引数の数が奇数の場合、暗黙の空の引数が追加され、最後のプレースホルダーの出現を効果的に削除します。
プレースホルダーも置換もNUL文字を含むことはできませんが、s が必要な場合\
など、標準のC エスケープを使用\0
できますNUL
(そのため、必要な場合は記述\\
する必要があります\
)。
posixのようなシステム(lexとcc)に存在する標準のビルドツールが必要です。
replaceholder() {
local dir=$(mktemp -d)
( cd "$dir"
{ printf %s\\n "%option 8bit noyywrap nounput" "%%"
printf '"%s" {fputs("%s", yyout);}\n' "${@//\"/\\\"}"
printf %s\\n "%%" "int main(int argc, char** argv) { return yylex(); }"
} | lex && cc lex.yy.c
) && "$dir"/a.out
rm -fR "$dir"
}
\
必要に応じて引数ですでにエスケープされていると想定しますが、存在する場合は二重引用符をエスケープする必要があります。これは、2番目のprintfの2番目の引数が行うことです。以来lex
デフォルトのアクションがありECHO
、我々はそれを心配する必要はありません。
実行例(懐疑的なタイミングでの、それは単なる安価な商品のラップトップです):
$ time echo AB | replaceholder A B B A
BA
real 0m0.128s
user 0m0.106s
sys 0m0.042s
$ time printf %s\\n AB{0000..9999} | replaceholder A B B A > /dev/null
real 0m0.118s
user 0m0.117s
sys 0m0.043s
入力が大きい場合は、最適化フラグをに提供すると便利な場合がcc
あり、現在のPosix互換性の場合はを使用することをお勧めしますc99
。さらに野心的な実装では、毎回生成するのではなく、生成された実行可能ファイルをキャッシュしようとする可能性がありますが、生成にコストがかかるとは限りません。
編集
tccを使用している場合は、一時ディレクトリを作成する手間を省くことができ、通常のサイズの入力に役立つコンパイル時間を短縮できます。
treplaceholder () {
tcc -run <(
{
printf %s\\n "%option 8bit noyywrap nounput" "%%"
printf '"%s" {fputs("%s", yyout);}\n' "${@//\"/\\\"}"
printf %s\\n "%%" "int main(int argc, char** argv) { return yylex(); }"
} | lex -t)
}
$ time printf %s\\n AB{0000..9999} | treplaceholder A B B A > /dev/null
real 0m0.039s
user 0m0.041s
sys 0m0.031s
tr AB BA
。