在PowerShell中将文件IO的-replace和Set-Content组合使用

3
我可以帮助您翻译。以下是需要翻译的内容:

我有以下脚本:

$allFiles = Get-ChildItem "./" -Recurse | Where { ($_.Extension -eq ".ts")}
foreach($file in $allFiles)
{
    # Find and replace the dash cased the contents of the files
    (Get-Content $file.PSPath) | 
        Foreach-Object {$_ -replace "my-project-name", '$appNameDashCased$'} |
        Set-Content $file.PSPath    

    # Find and replace the dash cased the contents of the files
    (Get-Content $file.PSPath) | 
        Foreach-Object {$_ -replace "MyProjectName", '$appNameCamelCased$'} |
        Set-Content $file.PSPath    

    # Find and replace the dash cased the contents of the files
    (Get-Content $file.PSPath) | 
        Foreach-Object {$_ -replace "myProjectName", '$appNamePascalCased$'} |
        Set-Content $file.PSPath    
}

它需要一个文件并进行一些替换,然后保存该文件。 然后它取出相同的文件并进行更多的替换,然后再次保存文件。 然后再做一次。

这个方法可以起作用,但似乎效率低下。

有没有一种方法可以先执行所有替换操作,然后再保存文件一次?

(如果可能,我希望保留PowerShell的易读样式。)


TheMadTechnician的回答得到了我的投票。当我看到你的代码时,还有其他一些事情:第一行很笨拙:“./”是Linux中的“here”,所以可以省略它,如果不指定路径,则Get-ChildItem会假定当前路径(和当前PS驱动器)。将输出导入Where-Object是可行的,但在此命令中效率低下,因为该命令具有内置过滤功能。另外,在你使用的where-object子句中,你在括号周围加了花括号。这些括号是不必要的。$allFiles = Get-ChildItem -recurse -Include "*.ts"。对于Get-Content,你只需要使用$file对象。Get-Content $file - Jeter-work
2个回答

3

当然,只需要在ForEach-Object块中链接您的替换即可:

$allFiles = Get-ChildItem "./" -Recurse | Where { ($_.Extension -eq ".ts")}
foreach($file in $allFiles)
{
    (Get-Content $file.PSPath) | 
        Foreach-Object {
            # Find and replace the dash cased the contents of the files
            $_ -replace "my-project-name", '$appNameDashCased$' `
               -replace "MyProjectName", '$appNameCamelCased$' `
               -replace "myProjectName", '$appNamePascalCased$'
        } |
        Set-Content $file.PSPath    
}

@Xalorous 我不太明白你的意思,请详细说明一下。我认为不需要任何额外的管道。 - briantist
当我意识到这是一个很长的命令时,我删除了我的评论。但是,你的代码在“-replace”行结束时没有任何东西来保持该行继续进行,我不确定以下一行以“-replace”开头是否会起作用。我认为你需要在前两个命令的末尾加上反引号。 - Jeter-work
当我运行这个程序时,会出现“未将'-replace'识别为cmdlet、函数、脚本文件或可操作的程序名称。”的错误提示。但是,如果我只保留第一个-replace行,则可以无错误地运行。(似乎它不喜欢这种组合方式...) - Vaccano
较新版本的Powershell使得命令可以分成多行,只要剩下的部分不构成完整的命令即可。最简单的方法是使用括号来说明。如果您有一个开放的括号表达式,它会自动跨越多行直到您关闭它。反斜杠字符是一种强制换行的方式,并告诉控制台将以下行视为续行。 - Jeter-work
@Vaccano 我试图通过添加换行符和反引号使其更易读,但你可以像TheMadTechnician的回答一样将它们都放在一行上。 - briantist

3
这是可以做到的,实际上比你正在做的要简单得多。您可以像这样链接-Replace命令:
$allFiles = Get-ChildItem "./" -Recurse | Where { ($_.Extension -eq ".ts")}
foreach($file in $allFiles)
{
    # Find and replace the dash cased the contents of the files
    (Get-Content $file.PSPath) -replace "my-project-name", '$appNameDashCased$' -replace "StringB", '$SecondReplacement$' -replace "StringC", '$ThirdReplacement$' | Set-Content $file.PSPath
}

不错!我认为 Set-Content 可能会因为管道而失败,因此他用括号包装了 Get-Content 来强制先读取整个文件,但这也可以轻松应用于这个问题。 - briantist
我在PowerShell 4.0中也尝试过,但那里也不起作用...抱怨不知道replace是什么。 - Vaccano
Get-Content 命令前后添加 () ,使其将 -Replace 应用于结果,而不是尝试将其解释为 Get-Content 的参数。这应该对您有用。 - TheMadTechnician

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接