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 perlrunHere we still need to enable
.
to match newlines as well, what it normally doesn't, with the/s
modifier. See Modifiers in perlreSince
"
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 variableThe
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 <> operatorI use
qq
operator for double quotes since"
is a delimiter on Windows command-line
(I cannot test on Windows right now)