如何在Perl窗口中删除大量文本后添加新行?

6pp0gazn  于 2022-11-24  发布在  Perl
关注(0)|答案(1)|浏览(134)

我尝试在插入几行新行之前删除文件中的大量文本。我可以使用如下一行代码删除单词“CAParticleSystemDefinition”之后的所有内容

perl -0777 -pi -we "s/CParticleSystemDefinition\x22\K.*/\n}/s" "D:\Steam\steamapps\common\dota 2 beta\content\dota_addons\custom\particles\generic_gameplay\winter_effects_creep.vpcf"

但是,当我尝试稍微修改代码,使其添加几个类似这样的新行时,它不起作用

perl -0777 -pi -we "s/CParticleSystemDefinition\x22\K.*/\n      m_Children = \n    [\n        {\n            m_ChildRef = resource:\x22particles/generic_gameplay/winter_effects_breath.vpcf\x22\n        },\n    ]\n}/s" "D:\Steam\steamapps\common\dota 2 beta\content\dota_addons\custom\particles\generic_gameplay\winter_effects_creep.vpcf"

所以,基本上,我想做的是把这个文件

{
    _class = "CParticleSystemDefinition"
    m_bShouldHitboxesFallbackToRenderBounds = false
    m_nMaxParticles = 24
    m_flConstantRadius = 15.000000
    m_flConstantLifespan = 0.500000
    m_ConstantColor = 
    [
        212,
        170,
        145,
        255,
    ]
    m_bShouldSort = false
    m_Renderers = 
    [
        {
            _class = "C_OP_RenderSprites"
            m_nSequenceCombineMode = "SEQUENCE_COMBINE_MODE_USE_SEQUENCE_0"
            m_bMod2X = true
            m_nOrientationType = 3
            m_hTexture = resource:"materials/particle/footprints/footprints_generic.vtex"
            m_flAnimationRate = 1.000000
        },
    ]
    m_Emitters = 
    [
        {
            _class = "C_OP_ContinuousEmitter"
            m_flEmitRate = 10.000000
            m_flStartTime = 0.500000
            m_nScaleControlPoint = 5
        },
    ]
}

看起来像这样

{
    _class = "CParticleSystemDefinition"
    m_Children = 
    [
        {
            m_ChildRef = resource:"particles/generic_gameplay/winter_effects_breath.vpcf"
        },
    ]
}
ckocjqey

ckocjqey1#

分两步完成--清除该短语后面的文件其余部分,然后添加所需的文本

perl -0777 -i.bak -wpe"s{Definition\x22\K.*}{}s; $_ .= qq(\n\tm_Children...)"  file

为了清楚起见,我用省略号表示其余部分。我添加了.bak以保存备份文件,直到测试足够好。
当然,在替换部分中添加字符串也是可以的--我不太清楚代码中的哪些地方失败了(以及是如何失败的?)。将其分为两个步骤只会使检查和组织起来更容易,但也可以使用/e修饰符在替换部分中运行代码

perl -0777 -i.bak -wpe"
    s{Definition\x22\K.*}{
        # any valid Perl code, what it evaluates to is used as replacement
        qq(\n\tm_Children...)
    }es;
"  file

如果你不想使用制表符(制表符可能会扩展,也可能不会扩展,这取决于各种设置和对它所做的操作),可以准备并使用一串空格来代替。

perl -0777 -i.bak -wpe"
    s{Definition\x22\K.*}{}s; 
    $s4 = q( ) x 4;  # four spaces
    $_ .= qq(\n${s4}m_Children =\n$s4) . join qq(\n$s4), 
        q([),
        q({), 
        qq($s4).q(m_ChildRef = ...)  # etc
        qq(\n)
" file

现在,如果有很多行的话,你可以将它变成一个更好的系统(例如,为每一个新的缩进级别添加一个合适的编程结构,比如map,这样就可以在一个语句中为所有行添加缩进)--或者如果只有几行的话,就压缩它。
同样,这可以在正则表达式的替换端内部运行,并带有额外的/e修饰符。
这也可以在一个通道中逐行完成,使用读写(+<)模式打开

perl -MPath::Tiny -wE"
    $f = shift // die qq(Need a filename); 
    open $fh, qq(+<), $f or die qq(Cant open $f: $!);
    while (<$fh>) { last if /Definition\x22$/ };       # past the spot to keep
    truncate $fh, tell($fh);                           # remove the rest
    say qq(File now:\n), path($f)->slurp;              # (just to see it now)
    say $fh $_ for                                     # add new content
        qq(new line 1), 
        qq(new line 2)  
" filename

(注意读写方式,请先仔细阅读文档)

相关问题