Powershell替换文件夹内所有文件中的字符串

时间:2018-06-09 18:48:38

标签: regex powershell

我正在尝试运行一个powershell脚本,它将用另一个字符串替换字符串的出现。我想从include中删除尖括号,并用双引号替换它们,只有头文件名,而不是Header文件名之前的文件夹路径。 示例:

#include <a/b/c/def.hpp>
#include <a/b/c/ddd.hpp> 

#include "def.hpp"
#include "ddd.hpp"

我试过这个。

(Get-ChildItem -Recurse | Get-Content | Select-String -Pattern "#include <a/b/c/")-replace '#include <a/b/c/(\w+).*/', '#include "'-replace '>','"'

有了这个,我得到了想要的结果,但是我无法使用结果并替换源文件中的现有行。

提前致谢。

我必须在一个文件夹中查询最多100个文件。 请建议最好的方法。

    INPUT 
#include <a0/b/c/d/HeaderFile1.hpp>
#include <a1/b/c/d/HeaderFile2.hpp>
#include <a2/b/c/d/HeaderFile3.hpp>
#include <a3/b/c/d/HeaderFile4.hpp>
#include <a4/b/c/d/HeaderFile5.hpp>
#include <a5/b/c/d/HeaderFile6.hpp>   


OUTPUT
#include "HeaderFile1.hpp"
#include "HeaderFile2.hpp"
#include "HeaderFile3.hpp"
#include "HeaderFile4.hpp"
#include "HeaderFile5.hpp"
#include "HeaderFile6.hpp"

3 个答案:

答案 0 :(得分:2)

您只需将新文本写回文件即可。这是我的方式:

Get-ChildItem -Recurse -File | ForEach-Object {

    (Get-Content $_).replace('#include <a/b/c/def.hpp>','#include "def.hpp"') | Set-Content $_
}

修改

现在你已经解释了你的问题,很明显你需要使用正则表达式。一个LotPings发布的将工作得很好。所以使用他的RegEx正确答案是:

Get-ChildItem -Recurse -File | ForEach-Object {

    (Get-Content $_)-replace('(?<=#include ).*\/([^>]+)>','"$1"') | Set-Content $_
}

答案 1 :(得分:2)

我创建了一些包含样本的测试文件:

> Select-String file*.cpp -patt 'hpp'

File1.cpp:1:#include <a0/b/c/d/HeaderFile1.hpp>
File2.cpp:1:#include <a1/b/c/d/HeaderFile2.hpp>
File3.cpp:1:#include <a2/b/c/d/HeaderFile3.hpp>
File4.cpp:1:#include <a3/b/c/d/HeaderFile4.hpp>
File5.cpp:1:#include <a4/b/c/d/HeaderFile5.hpp>
File6.cpp:1:#include <a5/b/c/d/HeaderFile6.hpp>

以下脚本使用RegEx在RegEx101及以下静态解释。

## Q:\Test\2018\06\09\SO_50777494.ps1
## the following RegEx usees a positive lookbehind and a
## capture group for the filename.

[RegEx]$Search = '(?<=#include ).*\/([^>]+)>'
$Replace = '"$1"'

ForEach ($File in (Get-ChildItem -Path '.\File*.cpp' -Recurse -File)) {
    (Get-Content $File) -Replace $Search,$Replace |
        Set-Content $File
}

替换后的Select-String的示例输出:

> sls file*.cpp -patt 'hpp'

File1.cpp:1:#include "HeaderFile1.hpp"
File2.cpp:1:#include "HeaderFile2.hpp"
File3.cpp:1:#include "HeaderFile3.hpp"
File4.cpp:1:#include "HeaderFile4.hpp"
File5.cpp:1:#include "HeaderFile5.hpp"
File6.cpp:1:#include "HeaderFile6.hpp"

RegEx的解释:

(?<=#include ).*\/([^>]+)>
  Positive Lookbehind (?<=#include )
  Assert that the Regex below matches
  #include matches the characters #include literally 
  .*
    . matches any character (except for line terminators)
    * Quantifier — Matches between zero and unlimited times, 
      as many times as possible, giving back as needed (greedy)
  \/ matches the character / literally (case sensitive)
  1st Capturing Group ([^>]+)
    Match a single character not present in the list below [^>]+
    + Quantifier — Matches between one and unlimited times, 
      as many times as possible, giving back as needed (greedy)
  > matches the character > literally (case sensitive)

答案 2 :(得分:1)

编辑:测试您提供的示例,如果格式可能不同(更深的路径,路径中的特殊字符等)请先测试。并备份

这样的事情应该有效:

$items = Get-ChildItem -Recurse
foreach ($i in $items) {
 $newContent = (Get-Content $i) -replace('#include <((\w)+\/)*(\w+\.hpp)>','#include "$3"')
 $newContent | Set-Content $i
}