Home > Back-end >  How do I add new lines after deleting a large amount of text in Perl windows?
How do I add new lines after deleting a large amount of text in Perl windows?

Time:07-15

I'm trying to remove a large amount of text from a file before inserting a few new lines. I can delete everything after the word 'CParticleSystemDefinition' with a single line of code like this

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"

But when I try to change the code slightly so that it adds a few new lines like this, it doesn't work

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"

So, basically, what I want to do is make this file

{
    _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
        },
    ]
}

look like this

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

CodePudding user response:

Do it in two steps -- clear the rest of the file after that phrase, then add the desired text

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

where I've used ellipses to indicate the rest, for clarity. I added .bak to keep a backup file, until this is tested well enough.


If you don't want tabs, which may or may not get expanded depending on various settings and on what's done with this, can build the replacement more systematically

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

Now one can either build this into a better system (adding a suitable programming construct for each new level of indentation for example, like map over such lines so to add indentation to all in one statement), if there is a lot -- or condense it if there's really just a few lines.


This can be done line-by-line in one pass as well, using the read-write ( <) mode for open

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

(Carefully with read-write modes. Please read the docs with care first.)

  • Related