Multiline string replace with pretty indentation

偶尔善良 提交于 2020-01-16 05:12:31

问题


I want to do multi-line string replacements in some template files, but retain a pretty indentation.

Here's an example of the template:

<TAG1>
    <TAG2>
        %REPLACETHIS%
    </TAG2>
</TAG1>

Now, when I simply replace the string %REPLACETHIS% with a string like

<REPLACEDSTRINGTAG1>
    replacedstringtext
</REPLACEDSTRINGTAG1>

it will look something like:

    <TAG1>
        <TAG2>
            <REPLACEDSTRINGTAG1>
    replacedstringtext
</REPLACEDSTRINGTAG1>
        </TAG2>
    </TAG1>

when it should look like:

    <TAG1>
        <TAG2>
            <REPLACEDSTRINGTAG1>
                replacedstringtext
            </REPLACEDSTRINGTAG1>
        </TAG2>
    </TAG1>

It gets even more complicated because the template will be part of a bigger template where it should be indented correctly as well.

I'm trying to achieve this in Perl, but basically the problem is the same in all the languages I know.

Has anyone a better idea than to just replace line-by-line with variables that keep track of the current indent depth? Which is very cumbersome due to the multi-level-template structure.

Basically, what I need is a substitute for a simple regex that will not only put the first line of the substitution string at the right column, but puts every line on that column. So if %REPLACETHIS% is at column 10, all the lines in the replacement string should be put at col 10... maybe there is some tricky built-in magic with regexes in Perl?


回答1:


Now that your template files are in XML format, you could use some XML processing modules to handle it. It's more flexible and reliable.

For your case, XML::LibXML could handle perfectly:

use XML::LibXML;
use XML::LibXML::PrettyPrint;

my $xml = "template.xml";
my $parser = XML::LibXML->new();
my $tree = $parser->parse_file($xml);
my $root = $tree->getDocumentElement;

my ($replace_node) = $root->findnodes('/TAG1/TAG2');
$replace_node->removeChildNodes();
my $new_node = $tree->createElement('REPLACEDSTRINGTAG1');
$new_node->appendText('replacedstringtext');
$replace_node->addChild($new_node);

my $pp = XML::LibXML::PrettyPrint->new(indent_string => "\t");
$pp->pretty_print($tree);
print $tree->toString;



回答2:


Not convinced regex is the correct approach for this, however if you use a group to capture the indentation before %REPLACETHIS%, you can just enter it back into the subsitution.

e.g.

s/(.*)%REPLACTHIS%/$1<REPLACEDSTRINGTAG1>\n$1    replacedstringtext\n$1</REPLACEDSTRINGTAG1>

DEMO



来源:https://stackoverflow.com/questions/25501949/multiline-string-replace-with-pretty-indentation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!