Grep | sed -i等效于Windows

时间:2019-03-14 02:30:56

标签: bash powershell

我正在尝试将此命令复制到PowerShell:

grep -lR 'Find' ./src | while read filename; do sed -i".bak" 's/Find/Replace/g' "$filename"; done 

到目前为止我所拥有的:

Get-ChildItem "src" -Recurse -File | ForEach-Object { $f = $_; (Get-Content $f) | ForEach-Object { $_ -replace "Find", "Replace" } | Set-Content "$f.tmp"; Move-Item "$f.tmp" $f -Force }

我遇到一个错误,说"filename.tmp" does not exist。我认为以上将在解析时创建文件。任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:1)

您很可能已成为Windows PowerShell对System.IO.FileInfo输出的Get-ChildItem实例的不一致字符串化的牺牲品-请参见this answer

解决方法是通过.FullName属性使用显式字符串化,该属性显式返回项目的完整路径。

已应用于您的命令,并进行了一些优化:

Get-ChildItem -File -Recurse src | ForEach-Object { 
   $f = $_.FullName  # !! Explicitly retrieve the full path
   (Get-Content $f -Raw) -creplace 'Find', 'Replace' | 
     Set-Content -NoNewline "$f.tmp"
   Move-Item "$f.tmp" $f -Force
}
  • Get-Content -Raw将整个文件作为单个字符串读入内存,这效率更高。

  • -creplace(执行区分大小写替换,默认情况下将执行sed)直接应用于生成的多行字符串并替换所有出现的字符串。 / p>

  • -NoNewline(PSv5 +)确保Set-Content不会在要保存的多行字符串中添加 additional 尾随换行符(对{{1 }} / Out-File)。

  • 注意:假设>预先读取了整个文件,您甚至可以将修改后的内容写回到同一文件中,而无需中间临时文件和后续的Get-Content -Raw呼叫;也就是说,如果写回同一文件的过程被中断,这样做会带来轻微的数据丢失风险。

    • 此外,尽管您的Move-Item调用保留扩展名为sed的原始文件,但您的PowerShell命令却没有。