多行字符串替换为漂亮的缩进

时间:2014-08-26 09:05:32

标签: regex string perl replace indentation

我想在一些模板文件中进行多行字符串替换,但保留一个漂亮的缩进。

这是模板的一个示例:

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

现在,我只需将字符串%REPLACETHIS%替换为类似

的字符串
<REPLACEDSTRINGTAG1>
    replacedstringtext
</REPLACEDSTRINGTAG1>

它看起来像:

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

应该是这样的:

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

它变得更加复杂,因为模板将成为更大模板的一部分,它也应该正确缩进。

我试图在Perl中实现这一点,但基本上我所知道的所有语言中的问题都是一样的。

有没有人比通过跟踪当前缩进深度的变量逐行替换更好的想法?由于多级模板结构,这非常麻烦。

基本上,我需要的是一个简单的正则表达式的替代品,它不仅将替换字符串的第一行放在右列,而且将每一行放在该列上。因此,如果%REPLACETHIS%位于第10列,替换字符串中的所有行都应该放在第10列......也许在Perl中有一些带有正则表达式的棘手的内置魔法?

2 个答案:

答案 0 :(得分:2)

现在您的模板文件是XML格式,您可以使用一些XML处理模块来处理它。它更灵活可靠。

对于您的情况,XML::LibXML可以完美处理:

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;

答案 1 :(得分:1)

不相信正则表达式是正确的方法,但如果您使用组来捕获%REPLACETHIS%之前的缩进,则可以将其输入到替换中。

e.g。

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

DEMO