【问题标题】:parse multilines from a file and replace从文件中解析多行并替换
【发布时间】:2015-05-06 14:43:39
【问题描述】:

我需要读取一个内容如下的文件:

Computer Location = afp.local/EANG
Description = RED_TXT
Device Name = EANG04W
Domain Name = afp.local
Full Name = Admintech
Hardware Monitoring Type = ASIC2
Last Blocked Application Scan Date = 1420558125
Last Custom Definition Scan Date = 1348087114
Last Hardware Scan Date = 1420533869
Last Policy Sync Date = 1420533623
Last Software Scan Date = 1420533924
Last Update Scan Date = 1420558125
Last Vulnerability Scan Date = 1420558125
LDAP Location = **CN=EANG04W**,OU=EANG,DC=afp,DC=local
Login Name = ADMINTECH
Main Board OEM Name = Dell Inc.
Number of Files = 384091
Primary Owner = **CN= LOUHICHI anoir**,OU=EANG,DC=afp,DC=localenter code here

我需要将CN=$value 替换为CN=Compagny,其中$value 是在CN= 之后和, 之前检索的内容。

【问题讨论】:

  • 是否要将修改后的文本保存到新文件中?
  • 那么问题出在哪里?读取文件?改变内容?保存输出?添加你的脚本并解释什么是麻烦的部分。
  • 我试过这个代码: $file = 'D:\sources\scripts\2.txt' $content = Get-Content $file | foreach ($line in $content) { if ($line.Contains('CN=')) { $variable = $line.Split(',').Split('=')[2] $variable1 = $variable -replace $variable, "Compagny" } Set-Content -path $file } 但似乎语法不正确!谢谢(我需要将更改后的文本保存到同一个文件)

标签: parsing powershell multiline


【解决方案1】:

好的,所以你真的应该更新你的问题而不是在评论中发布代码,因为它真的很难阅读。这就是我认为你的意图:

$file = 'D:\sources\scripts\2.txt' 
$content = Get-Content $file | foreach ($line in $content) { 
    if ($line.Contains('CN=')) { 
        $variable = $line.Split(',').Split('=')[2] 
        $variable1 = $variable -replace $variable, "Compagny" 
    } Set-Content -path $file 
}

这肯定有一些语法错误。第一行很棒,您定义了路径。然后事情就出错了......您对Get-Content 的调用很好,它将获取文件的内容,并将它们发送到管道中。

您将它直接导入ForEach 循环,但它是错误的类型。你真正想要的是一个ForEach-Object 循环(这可能会令人困惑,因为在这样的管道中使用它时可以缩短为ForEach)。 ForEach-Object 循环不声明内部变量(例如($line in $content)),而是脚本块使用自动变量$_。所以你的循环需要变成这样:

Get-Content $file | ForEach { <do stuff> } | Set-Content

接下来让我们看看这个循环的内部。您使用If 语句来查看该行是否包含“CN=”、可理解和功能。如果是这样,则将行拆分为逗号,然后再次拆分为等号,选择第二条记录。嗯,您在拆分一个字符串的任何时候都会创建一个字符串数组,并且您已经拆分了两次字符串,但只指定要在第二次拆分时使用该数组的哪个记录。那可能是个问题。无论如何,您将该子字符串分配给$variable,然后将整个内容替换为“公司”并将该输出存储到$variable1。所以这里有几个问题。在逗号上拆分字符串后,您将拥有以下字符串数组:

"LDAP Location = **CN=EANG04W**"
"OU=EANG"
"DC=afp"
"DC=local"

这是一个包含 4 个字符串对象的数组。因此,您尝试在等号上至少拆分其中一个(因为您没有指定哪一个)。您现在有一个包含 4 个数组对象的数组,其中每个对象都有 2 个字符串对象:

("LDAP Location", "**CN", "EANG04W**")  
("OU", "EANG")  
("DC","afp")  
("DC","local")  

此时您确实指定了第三条记录(PowerShell 中的数组从记录 0 开始,因此 [2] 指定了第三条记录)。但是您没有指定第一个数组中的哪条记录,所以它只会抛出错误。假设您实际上选择了您真正想要的东西,我猜那将是“EANG04W”。 (顺便说一句,那将是$_.Split(",")[0].Split("=")[1])。然后将其分配给$Variable,并继续将其全部替换为“公司”,因此在 PowerShell 扩展变量后,它会如下所示:

$variable1 = "EANG04W" -replace "EANG04W", "company"

好的,您刚刚成功地将“公司”分配给了一个变量。你的 If 语句到此结束。您永远不会从 If 语句中输出任何内容,因此 Set-Content 无需设置任何内容。此外,它会为通过管道传输到 ForEach 语句的每一行设置任何内容,每次都重新编写文件,但幸运的是,该脚本不起作用,因此它没有删除您的文件。另外,由于您试图通过管道传输到 Set-Content,因此管道末端没有输出,因此您绝对没有为 $content 分配任何内容。

那么让我们尝试修复它,好吗?第一行?效果很好!不用找了。现在,我们没有在变量中保存任何内容,我们只是想更新文件的内容,所以不需要$Content =。那我们就继续前进,好吗?我们将Get-Content 通过管道传输到ForEach 循环中,就像您尝试做的那样。一旦进入ForEach 循环,我们将做一些不同的事情。 -replace 方法执行 RegEx 匹配。我们可以在这里利用它来发挥我们的优势。我们将为每一行替换您感兴趣的文本,如果找不到,则不会进行替换,并将每一行传递到管道中。 ForEach 的内部看起来像这样:

$_ -replace "(<=CN\=).*?(?=,)", "Company"

可以在此处查看该 RegEx 匹配的细分:https://regex101.com/r/gH6hP2/1
但是,假设它会查找紧接在其前面有“CN=”的文本,并一直到它后面的第一个逗号。在您的示例中,这包括两个尾随星号,但不触及前导星号。那是你的意图吗?这将使您的示例文件的最后一行:

Primary Owner = **CN=Company,OU=EANG,DC=afp,DC=localenter code here

好吧,如果这符合预期,那么我们就有了赢家。现在我们关闭ForEach 循环,并将输出通过管道传输到Set-Content,一切就绪!就个人而言,我强烈建议输出到一个新文件,以防您以后由于某种原因需要引用原始文件,所以这就是我要做的。

$file = 'D:\sources\scripts\2.txt'
$newfile = Join-Path (split-path $file) -ChildPath ('Updated-'+(split-path $file -Leaf))
Get-Content $file | ForEach{$_ -replace "(?<=CN\=).*?(?=,)", "Company"} | Set-Content $newfile

好的,就是这样。该代码将生成具有以下内容的 D:\sources\scripts\Updated-2.txt:

Computer Location = afp.local/EANG
Description = RED_TXT
Device Name = EANG04W
Domain Name = afp.local
Full Name = Admintech
Hardware Monitoring Type = ASIC2
Last Blocked Application Scan Date = 1420558125
Last Custom Definition Scan Date = 1348087114
Last Hardware Scan Date = 1420533869
Last Policy Sync Date = 1420533623
Last Software Scan Date = 1420533924
Last Update Scan Date = 1420558125
Last Vulnerability Scan Date = 1420558125
LDAP Location = **CN=Company,OU=EANG,DC=afp,DC=local
Login Name = ADMINTECH
Main Board OEM Name = Dell Inc.
Number of Files = 384091
Primary Owner = **CN=Company,OU=EANG,DC=afp,DC=localenter code here

【讨论】:

  • 非常感谢您的帮助和详细信息 解释得很好,很有用 问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
相关资源
最近更新 更多