试图替换文件中的字符串但替换太多

Trying to replace strings in a file but its replacing too much

我正在尝试通过 txt 日志文件将 PowerShell 脚本组合到 运行 并删除域名/url。

到目前为止,我只是对文件进行查找替换,但是当我尝试这样做时,它并没有像我期望的那样工作,例如

如果我有一个包含以下内容的文本文件:

intranet.contoso.com and some text

在我的脚本 运行 将 intranet.contoso.com 替换为 DOMAIN1 之后,我得到的输出是

DOMAIN1 DOMAIN1aDOMAIN1nDOMAIN1dDOMAIN1 DOMAIN1sDOMAIN1oDOMAIN1mDOMAIN1eDOMAIN1 DOMAIN1tDOMAIN1eDOMAIN1xDOMAIN1tDOMAIN1

所以我不确定我哪里出错了。到目前为止我的代码是

$domains = ,("mydomain.net","mydomain"),("yourdomain.net","yourdomain"),("mydomain2.net","mydomain2")
$path = Read-Host "Please enter the full path to the directory containing the files to be sanatized"

    $files = Get-ChildItem –Path $path *.txt
    foreach ($file in $files)
    {
        for($x=0; $x -lt $domains.Count; $x++)
        {
            (Get-Content $file.PSPath) |
            Foreach-Object { $_ -replace $domains[$x][0], "DOMAIN$($x+1)" } |
            Set-Content $file.PSPath

            (Get-Content $file.PSPath) |
            Foreach-Object { $_ -replace $domains[$x][1], "DOMAIN$($x+1)" } |
            Set-Content $file.PSPath

        }
    }

正如其他两个答案所指出的那样,数组的数组与 ,(x,y,),(foo,bar)" syntax. Use of@` 混淆了,或者只是删除了前导逗号就可以解决这个问题。

我还发现写入与您正在读取的文件相同的文件对我来说效果不佳,即使使用 (Get-Content $file.PSPath) 语法也是如此。通过写入新文件然后重命名,我获得了更一致的结果。

我认为您遇到的问题是您创建多维数组的方式。当我使用你的线路时,我得到了一些非常不同的东西。

尝试将第一行重写为(数组的数组):

$domains = @(@("mydomain.net","mydomain"),@("yourdomain.net","yourdomain"),@("mydomain2.net","mydomain2"))

我确定您的主要问题是在定义 $domains 时使用了 unary operator。如果你看看你的第一个元素。

PS D:\temp> $domains[0]
mydomain.net
mydomain

如您所料,但这是问题发生的下一步。让我们尝试获取 "mydomain" 字符串

PS D:\temp> $domains[0][1]

什么都没有?这很奇怪。不,如果你知道发生了什么,就不会真的。让我们看看这个锯齿状数组的另一个元素。

PS D:\temp> $domains[0][0]
mydomain.net
mydomain

这是什么鬼话?数组第一个元素的第一个元素是另一个数组。现在看这个:

PS D:\temp> $domains[0][0][1]
mydomain

有几个步骤前我们试图获取的元素。您创建了一个数组,其中第一个元素是一个包含两个元素的数组。

你的测试文件看起来像它那样的原因是第一个例子会尝试使用 $domains[0][1] 这将是 null 并匹配字符之间的每个 space 因此你的输出。

简单删除一元运算符。

$domains = ("mydomain.net","mydomain"),("yourdomain.net","yourdomain"),("mydomain2.net","mydomain2")

还值得注意的是 -replace 是一个正则表达式运算符,因此您需要小心地在匹配字符串中使用元字符。例如期间。静态正则表达式方法 escape 可以为您解决这个问题,以确保您的字符串按字面匹配。

$_ -replace [regex]::Escape($domains[$x][1]), "DOMAIN$($x+1)"

知道 -replace 也是一个数组运算符,您还可以改进替换逻辑。所以在你的循环中你可以替换这个

(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace $domains[$x][0], "DOMAIN$($x+1)" } |
Set-Content $file.PSPath

(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace $domains[$x][1], "DOMAIN$($x+1)" } |
Set-Content $file.PSPath

有了这个。

(Get-Content $file) -replace $domains[$x][0], "DOMAIN$($x+1)"  -replace $domains[$x][1], "DOMAIN$($x+1)" |
Set-Content $file

.pspath while valid 不是必需的。 cmdlet Get/Set-Content 将根据 $file 对象中的参数名称匹配路径。我真的帮不上什么忙。这是未经测试的,因为我没有方便的示例文本文件。测试并测试更多以确保。