在 Perl Windows 中,如何替换单词后的所有内容?

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

我是 Perl 的新手,我想替换其中的一段文字

<!-- 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
        },
    ]
}

到此。

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

这是我一直在使用的命令:

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

它一直在为我产生这个结果

<!-- 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
        },
    ]
}

那么,我该如何做到替换某些内容会删除它之后的所有内容? 我还想将命令保留在一行中。

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

也需要匹配它之后的所有内容,但在替换中将其遗漏

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

说明

  • 使用 -p 程序(在 "" 之间)一次应用于一行。因此,要一次匹配多行,根据这里的需要,我们需要将整个文件读入一个字符串,-0777 所做的;那么我们应用代码的“行”就是整个文件。参见 Command switches in perlrun

  • 这里我们仍然需要使用 /s 修饰符启用 . 来匹配换行符,它通常不会匹配换行符。参见 Modifiers in perlre

  • 由于" 在Windows 中分隔程序文本,我在代码中使用\x22(十六进制)作为" 字符。 (在我对 Linux 的测试中,用 \" 转义它没有用,但它可能对 Windows 有效,我现在无法测试。)

  • \K 删除(“忘记”)该点之前的所有匹配项,因此它们不会从字符串中消耗掉;所以我们不必 re-enter 在替换部分中使用它们。因此只有下面的 .* 被替换为 \n},所以除了需要的换行符和结束分隔符之外。参见 \K in perlre

查看教程perlretut


出现了一个问题,如何将文件列表传递给 Windows 中的这个 command-line 程序,就像 *.vpcf 在 Unix 世界中所做的那样(所有文件以结尾.vpcf).

这是Windowsshell(s)的问题,Windows中的cmd.exe不是简单的问题,而是PowerShell。所以这是使用 PowerShell 的一种方法。

另一方面,可以让 Perl 程序执行此操作 -- 将模式传递给它以构建文件名,例如扩展名,并让它构建文件列表、读取、编辑和写回文件。那么该程序将比上面的 one-liner 复杂一些,但仍然相当基础。

这是一个快捷方式,仍然保持它作为一个简短的 command-line 程序 ("one-liner")

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

(与上面相同的正则表达式)

评论

  • 文件列表是使用 glob 从调用程序时传递给程序的内容构建的(其 @ARGV 数组中的第一个参数),然后将其分配给 @ARGV(稍后 <>

  • 要模拟 -i.bak 可以使用 $^I variable

  • while (<>)@ARGV 中列出的每个文件中取出一行。 (通常这些是来自 command-line 的东西,但现在我们明确分配给 @ARGV。)见 <> operator

  • 我使用 qq 运算符作为双引号,因为 " 是 Windows command-line

    上的分隔符

(我现在无法在 Windows 上进行测试)