Home > database >  In Perl Windows, how do you replace everything after a word?
In Perl Windows, how do you replace everything after a word?

Time:04-12

I'm new to Perl and I'd like to replace a text from this

<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{aafc65d8-7a5a-4e01-bd8d-3ac118422503} -->
{
    _class = "CParticleSystemDefinition"
    m_bShouldHitboxesFallbackToRenderBounds = false
    m_nMaxParticles = 1
    m_nInitialParticles = 1
    m_flConstantRadius = 15.000000
    m_ConstantColor = 
    [
        255,
        0,
        0,
        255,
    ]
    m_nConstantSequenceNumber = 8
    m_nConstantSequenceNumber1 = 7
    m_Renderers = 
    [
        
        {
            _class = "C_OP_RenderSprites"
            m_nSequenceCombineMode = "SEQUENCE_COMBINE_MODE_USE_SEQUENCE_0"
            m_bMod2X = true
            m_bDisableZBuffering = true
            m_hTexture = resource:"materials/particle/particle_modulate_01.vtex"
            m_nOrientationType = 2
        },
    ]
}

To this.

<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{aafc65d8-7a5a-4e01-bd8d-3ac118422503} -->
{
    _class = "CParticleSystemDefinition"
}

This is the command I've been using:

perl -pi.bak -e "s/CParticleSystemDefinition"/CParticleSystemDefinition"\n}/g;" "C:\Folder\File.vpcf"

and it has been producing this result for me

<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{aafc65d8-7a5a-4e01-bd8d-3ac118422503} -->
{
    _class = "CParticleSystemDefinition"
}
    m_bShouldHitboxesFallbackToRenderBounds = false
    m_nMaxParticles = 1
    m_nInitialParticles = 1
    m_flConstantRadius = 15.000000
    m_ConstantColor = 
    [
        255,
        0,
        0,
        255,
    ]
    m_nConstantSequenceNumber = 8
    m_nConstantSequenceNumber1 = 7
    m_Renderers = 
    [
        
        {
            _class = "C_OP_RenderSprites"
            m_nSequenceCombineMode = "SEQUENCE_COMBINE_MODE_USE_SEQUENCE_0"
            m_bMod2X = true
            m_bDisableZBuffering = true
            m_hTexture = resource:"materials/particle/particle_modulate_01.vtex"
            m_nOrientationType = 2
        },
    ]
}

So, how do I make it so that replacing something deletes everything that comes after it? I'd also like to keep the command on a single line.

CodePudding user response:

how do I make it so that replacing something deletes everything that comes after it?

Need to match all that after it, as well, but leave it out in the replacement

perl -0777 -pi.bak -we"s/CParticleSystemDefinition\x22\K.*/\n}/s" file

Explanation

  • With -p the program (between "") is applied to a line at a time. So to match multiple lines at once, as needed here, we need to read the whole file into a string, what -0777 does; then our "line" to which the code is applied is the whole file. See Command switches in perlrun

  • Here we still need to enable . to match newlines as well, what it normally doesn't, with the /s modifier. See Modifiers in perlre

  • Since " delimit the program text in Windows I use \x22 (hex) for the " character in code. (In my tests on Linux escaping it with \" didn't work but it may work on Windows, what I can't test now.)

  • The \K drops ("forgets") all matches previous to that point, so they are not consumed from the string; so we don't have to re-enter them in the replacement part. Thus only the following .* is replaced, with \n}, so removed apart from the needed newline and the closing delimiter. See \K in perlre

See the tutorial perlretut


A question came up of how to pass a list of files to this command-line program in Windows, like *.vpcf that one would do in Unix world (all files that end with .vpcf).

That is a question of Windows shell(s), and is not a simple matter with cmd.exe in Windows, but it is with PowerShell. So that's one way to go, use PowerShell.

On the other hand, one can have a Perl program do that -- pass it a pattern to build the filenames from, like the extension, and have it build a filelist, read and edit and write back the files. Then that will be a bit more involved program that the one-liner above, but still rather basic.

Here is a shortcut, to still keep it as a short command-line program ("one-liner")

perl -wE'@ARGV = glob qq($ARGV[0]); $^I = qq(.bak); while (<>) { s/.../.../s; print }' *.vpcf

(same regex as above)

Comments

  • The filelist is built using glob from what is passed to the program when it is invoked (first argument in its @ARGV array), then that is assigned to @ARGV (for <> later)

  • To emulate -i.bak one can use $^I variable

  • The while (<>) takes a line from each file listed in @ARGV. (Normally these are things passed on the command-line but now we explicitly assigned to @ARGV.) See <> operator

  • I use qq operator for double quotes since " is a delimiter on Windows command-line

(I cannot test on Windows right now)

  •  Tags:  
  • perl
  • Related