【问题标题】:Powershell, using contains to check if files contain a certain wordPowershell,使用 contains 检查文件是否包含某个单词
【发布时间】:2019-02-05 23:26:13
【问题描述】:

我正在尝试创建一个 powershell 脚本,它查看给定目录下的所有文件和文件夹,然后将 .properties 文件中给定单词的所有实例更改为另一个给定单词的实例。

我在下面写的内容是这样做的,但是我的版本控制会注意到每个文件中的更改,无论它是否包含要更改的单词的实例。为了解决这个问题,我尝试在获取/设置内容(如下所示)之前检查文件中是否存在该单词,但是它告诉我 [System.Object[]] 不包含名为“包含”的方法。我认为这意味着 $_ 是一个数组,所以我尝试创建一个循环来遍历它并一次检查每个文件,但它告诉我它无法索引到 System.IO.FileInfo 类型的对象。

谁能告诉我如何更改下面的代码以检查文件是否包含 wordToChange,然后应用它所做的更改。

$directoryToTarget=$args[0]
$wordToFind=$args[1]
$wordToReplace=$args[2]

Clear-Content log.txt

Get-ChildItem -Path $directoryToTarget -Filter *.properties -Recurse | where { !$_.PSIsContainer } | % { 


If((Get-Content $_.FullName).Contains($wordToFind))
{
    Add-Content log.txt $_.FullName
    (Get-Content $_.FullName) | 
     ForEach-Object { $_ -replace $wordToFind , $wordToReplace } | 
     Set-Content $_.FullName
}



}

谢谢!

【问题讨论】:

  • 请注意,您正在加载文件两次,考虑加载到变量中并对变量执行 -contains 和 -replace,可能会运行得更快...

标签: powershell


【解决方案1】:

试试这个:

$directoryToTarget=$args[0]
$wordToFind=$args[1]
$wordToReplace=$args[2]

Clear-Content log.txt

Get-ChildItem -Path $directoryToTarget -Filter *.properties -Recurse | where { !$_.PSIsContainer } | % { 

$file = Get-Content $_.FullName
$containsWord = $file | %{$_ -match $wordToFind}
If($containsWord -contains $true)
{
    Add-Content log.txt $_.FullName
    ($file) | ForEach-Object { $_ -replace $wordToFind , $wordToReplace } | 
     Set-Content $_.FullName
}

}

这会将文件的内容放入数组$file,然后检查每一行的单词。每行结果($true/$false)被放入数组$containsWord。然后检查该数组以查看是否找到该单词($True 变量存在);如果是这样,则运行 if loop

【讨论】:

  • 太棒了,谢谢。在旁注中,您能否想到 .properties 过滤器无法完全工作的原因。即使没有进行任何更改,它仍在查看 .sh 文件
  • 所以您只是在寻找扩展名为.properties 的文件?如果是这样,该过滤器应该可以正常工作...当您在 PowerShell shell (Get-ChildItem -Path $directoryToTarget -Filter *.properties -Recurse) 中单独键入 Get-ChildItem 时,您是否得到了列出的预期文件?
  • 另外,请查看this answer,它有另一种更适合我的情况的方法。
【解决方案2】:

简化的包含子句

$file = Get-Content $_.FullName

if ((Get-Content $file | %{$_ -match $wordToFind}) -contains $true) {
    Add-Content log.txt $_.FullName
    ($file) | ForEach-Object { $_ -replace $wordToFind , $wordToReplace } | 
    Set-Content $_.FullName
}

【讨论】:

  • 我建议在示例中使用 Foreach-object 而不是别名:%,因为这样对每个人都更容易理解。
  • 我同意,但这是一个“简化”的答案
【解决方案3】:

检查文件是否包含单词的最简单方法

如果我们查看 Get-Content 结果,我们会找到 string System.Array。所以,我们可以像 .NET 中的 System.Linq 一样:

content.Any(s => s.Contains(wordToFind));

在 PowerShell 中看起来像:

Get-Content $filePath `
            | %{ $res = $false } `
               { $res = $res -or $_.Contains($wordToFind) } `
               { return $res }

因此,我们可以在 cmdlet 中将其与文件路径和包含单词的参数聚合并使用它。还有一个:我们可以用-match而不是Contains使用Regex,这样会更灵活。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 2020-07-06
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多