2
votes

I am trying to use sed for transforming wikitext into latex code. I am almost done, but I would like to automate the generation of the labels of the figures like this:

[[Image(mypicture.png)]]

... into:

\includegraphics{mypicture.png}\label{img-1}

For what I would like to keep using sed. The current regex and bash code I am using is the following:

__tex_includegraphics="\\\\includegraphics[width=0.95\\\\textwidth]{$__images_dir\/"
__tex_figure_pre="\\\\begin{figure}[H]\\\\centering$__tex_includegraphics"
__tex_figure_post="}\\\\label{img-$__images_counter}\\\\end{figure}"

sed -e "s/\[\[Image(\([^)]*\))\]\].*/$__tex_figure_pre\1$__tex_figure_post/g"\

... but I cannot make that counter to be increased. Any ideas?

Within a more general perspective, my question would be the following: can I use a backreference in sed for creating a replacement that is different for each of the matches of sed? This is, each time sed matches the pattern, can I use \1 as the input of a function and use the result of this function as the replacement?

I know it is a tricky question and I might have to use AWK for this. However, if somebody has a solution, I would appreciate his or her help.

2
I would have opted for outputting static latex code that includes a latex counter and uses the value from that counter in the label. This way the latex is more maintainable later.Caleb

2 Answers

2
votes

You could read the file line-by-line using shell features, and use a separate sed command for each line. Something like

exec 0<input_file

while read line; do
    echo $line | sed -e "s/\[\[Image(\([^)]*\))\]\].*/$__tex_figure_pre\1$__tex_figure_post/g"
    __images_counter=$(expr $__images_counter + 1)
done

(This won't work if there are multiple matches in a line, though.)

For the second part, my best idea is to run sed or grep to find what is being matched, and then run sed again with the value of the function of the matched text substituted into the command.

2
votes

This might work for you (GNU sed):

sed -r ':a;/'"$PATTERN"'/{x;/./s/.*/echo $((&+1))/e;/./!s/^/1/;x;G;s/'"$PATTERN"'(.*)\n(.*)/'"$PRE"'\2'"$POST"'\1/;ba}' file

This looks for a PATTERN contained in a shell variable and if not presents prints the current line. If the pattern is present it increments or primes the counter in the hold space and then appends said counter to the current line. The pattern is then replaced using the shell variables PRE and POST and counter. Lastly the current line is checked for further cases of the pattern and the procedure repeated if necessary.