regex - Execute command defined by backreference in sed -


i creating primitive experimental templating engine based on sed (merely private enjoyment). 1 thing have been trying achieve several hours replace text patterns output of command contain.

to clearify, if input line looks

lorem {{echo ipsum}} 

i sed output this:

lorem ipsum 

the closest have come this:

echo 'lorem {{echo ipsum}}' | sed 's/{{\(.*\)}}/'"$(\\1)"'/g' 

which not work.

however,

echo 'lorem {{echo ipsum}}' | sed 's/{{\(.*\)}}/'"$(echo \\1)"'/g' 

gives me

lorem echo ipsum 

i don't quite understand happening here. why can give backreference echo command, cannot evaluate entire backreference in $()? when \\1 getting evaluated? thing trying achieve possible pure sed?

keep in mind entirely clear me trying achieve possible other tools. however, highly interested in whether possible pure sed.

thanks!

the reason attempt doesn't work $() expanded shell before sed called. reason can't use backreferences sed going capture.

it possible sort of thing gnu sed (not posix sed). main trick gnu sed has e flag s command makes replace pattern space (the whole space) result of pattern space executed shell command. means

echo 'echo foo' | sed 's/f/g/e' 

prints goo.

this can used use case follows:

echo 'lorem {{echo ipsum}}' | sed ':a /\(.*\){{\(.*\)}}\(.*\)/ { h; s//\1\n\3/; x; s//\2/e; g; s/\(.*\)\n\(.*\)\n\(.*\)/\2\1\3/; ba }' 

the sed code works follows:

:a                                    # jump label looping, in case there                                       # several {{}} expressions in line /\(.*\){{\(.*\)}}\(.*\)/ {            # if there {{}} expression,   h                                   # make copy of line   s//\1\n\3/                          # isolate surrounding parts   x                                   # swap original in   s//\2/e                             # isolate command, execute, output   g                                   # outer parts put hold                                       # buffer   s/\(.*\)\n\(.*\)\n\(.*\)/\2\1\3/    # rearrange parts put command                                       # output right place   ba                                  # rinse, repeat until {{}} covered } 

this makes use of sed's greedy matching in regexes capture last {{}} expression in line. note have difficulties if there several commands in line , 1 of later ones has multi-line output. handling case require definition of marker commands embedded in data not allowed have part of output , templates not allowed contain. suggest {{{}}}, lead to

sed ':a /\(.*\){{\(.*\)}}\(.*\)/ { h; s//{{{}}}\1{{{}}}\3/; x; s//\2/e; g; s/\(.*\)\n{{{}}}\(.*\){{{}}}\(.*\)/\2\1\3/; ba }' 

the reasoning behind template engine run trouble anyway if embedded commands printed further {{}} terms. convention impossible enforce, code pass template engine had better come trusted source, anyway.

mind you, not sure whole thing sane idea1. you're not planning use in sort of production code, you?

1i am, however, quite sure whether sane idea.


Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -