为什么运行“Get-Content”会返回一个 null 值表达式?

Why does running `Get-Content` return a null-valued expression?

提问人:Ooker 提问时间:10/11/2023 最后编辑:mklement0Ooker 更新时间:10/11/2023 访问量:74

问:

我运行以下命令:

Get-ChildItem -recurse -file | ForEach-Object { (Get-Content $_).Replace('hi there','hello') | Set-Content $_ } 

并收到此错误:

InvalidOperation: You cannot call a method on a null-valued expression.
InvalidOperation: You cannot call a method on a null-valued expression.

你知道这是为什么吗?

PowerShell null 表达式

评论

0赞 Santiago Squarzon 10/11/2023
如果文件没有内容(空文本文件),则由于不幸的枚举,可能会触发此事件。use 代替[System.IO.File]::ReadAllText($_.FullName).Replace(...(Get-Content $_)...

答:

2赞 mklement0 10/11/2023 #1

正如 Santiago Squarzon 所指出的 - 也许令人惊讶的是 - 使用 Get-Content 读取文件(字节)输出(无论您是否也使用 )。[1]0$null-Raw

调用任何方法都会导致您看到的错误。$null

一个简单的解决方案是过滤掉空文件,无论如何对它们执行任何替换都没有意义:

Get-ChildItem -Recurse -File |
  Where-Object Length -gt 0 |
  ForEach-Object {
    ($_ | Get-Content -Raw).Replace('hi there','hello') | 
      Set-Content -NoNewLine -LiteralPath $_.FullName
  }

请注意以下其他改进:

  • $_ | Get-Content等同于并确保每个输入文件都通过其完整路径传递,并且路径是逐字解释的。Get-Content -LiteralPath $_.FullName

  • -Raw确保将文件内容读取为单个(多行)字符串,从而加快替换速度。

  • -NoNewLine防止将额外的换行符附加到(可能已修改的)文件内容。Set-Content


[1] 从技术上讲,使用 -Raw 会发出一个“可枚举的 null”,即特殊的 [System.Management.Automation.Internal.AutomationNull]::Value 单例,指示缺少命令的输出。但是,在表达式(如方法调用)的上下文中,此值的处理方式与$null相同 - 有关详细信息,请参阅此答案
使用 -Raw,您可以争辩说应该返回空字符串而不是 $null,正如 GitHub 问题 #3911 中所建议的那样。

评论

0赞 Ooker 10/11/2023
这是什么意思?括号里的东西叫什么?这是什么语法?[System.Management.Automation.Internal.AutomationNull]::Value
1赞 mklement0 10/11/2023
@Ooker:是 PowerShell 类型文本 - 请参阅此答案。 是静态成员访问运算符。至于这个特殊单例的含义:看这个答案[<type name>]::