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
-pthe 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-0777does; 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/smodifier. 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
\Kdrops ("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
@ARGVarray), then that is assigned to@ARGV(for<>later)To emulate
-i.bakone 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
qqoperator for double quotes since"is a delimiter on Windows command-line
(I cannot test on Windows right now)
