Your problem is that .* is greedy, and matches like this:
${start}textcontent${end}something else${start}textcontent${end}
├───┬──┤├───────┬─────────────────────────────────┤├──┬──┤├──┬─┤
│ │ ┌──────────────────────────────┘ │
│ greedy │ ┌───────────────────────────┴┘ │
│ │ │ │ ┌─────────────────────┘
├───┴────────┤ │ ├──┴──┤ │ ├─────┴────┤
\\$\\{start\\} .* content .* \\$\\{end\\}
To fix that, make them reluctant by using .*?:
${start}textcontent${end}something else${start}textcontent${end}
├───┬──┤├─┬┤├──┬──┤├──┬─┤ ├──────┤├──┤├─────┤├────┤
│ │ │ └──────────────────┐
│ │ │ └┴───────────┐ │
│ │ └────────┐ │ │
│ └──────┐ │ │ │
├───┴────────┤ │ ├──┴──┤ │ ├─────┴────┤
\\$\\{start\\} .*? content .*? \\$\\{end\\}
The match would then repeat for the second sequence of ${start}...content...${end}.
In both cases, the second .* is matching an empty string.