【问题标题】:Powershell - Store hash table in file and read its contentPowershell - 将哈希表存储在文件中并读取其内容
【发布时间】:2021-03-02 05:45:40
【问题描述】:

Doug 建议跟进我之前关于匿名文件的问题 ( PowerShell - Find and replace multiple patterns to anonymize file) 我需要将所有哈希表值保存在单个文件“tmp.txt”中以供进一步处理。 示例:使用字符串处理输入文件后:

<requestId>>qwerty-qwer12-qwer56</requestId>

tmp.txt 文件包含:

qwerty-qwer12-qwer56 : RequestId-1

这是完美的。问题是在处理许多字符串时,在 tmp.txt 文件中有比应有的更多的对。在下面的 tmp.txt 示例中,我应该看到“RequestId-x”的 4 倍,但有 6 个。此外,当同一行上有 2 个或更多“匹配”时,只有第一个被更新/替换。知道这些额外的行是从哪里来的吗?为什么脚本不会继续检查到同一行的末尾?
这是我的测试代码:

$log = "C:\log.txt"
$tmp = "C:\tmp.txt"
Clear-Content $log
Clear-Content $tmp

@'
<requestId>qwerty-qwer12-qwer56</requestId>qwertykeyId>Qwd84lPhjutf7Nmwr56hJndcsjy34imNQwd84lPhjutZ7Nmwr56hJndcsjy34imNPozDr5</ABC reportId>poGd56Hnm9q3Dfer6Jh</msg:reportId>
<requestId>zxcvbn-zxcv12-zxcv56</requestId>
<requestId>qwerty-qwer12-qwer56</requestId>abcde reportId>plmkjh8765FGH4rt6As</msg:reportId>
<requestId>1234qw-12qw12-12qw56</requestId>
keyId>Qwd84lPhjutf7Nmwr56hJndcsjy34imNQwd84lPhjutZ7Nmwr56hJndcsjy34imNPozDr5</
keyId>Qwd84lPhjutf7Nmwr56hJndcsjy34imNQwd84lPhjutZ7Nmwr56hJndcsjy34imNPozDr5</
keyId>Zdjgi76Gho3sQw0ib5Mjk3sDyoq9zmGdZdjgi76Gho3sQw0ib5Mjk3sDyoq9zmGdLkJpQw</
reportId>plmkjh8765FGH4rt6As</msg:reportId>
reportId>plmkjh8765FGH4rt6As</msg:reportId>
reportId>poGd56Hnm9q3Dfer6Jh</msg:reportId>
'@ | Set-Content $log -Encoding UTF8

$requestId = @{
    Count   = 1
    Matches = @()
}
$keyId  = @{
    Count   = 1
    Matches = @()
}
$reportId  = @{
    Count   = 1
    Matches = @()
}

$output = switch -Regex -File $log {
    '(\w{6}-\w{6}-\w{6})' {
        if(!$requestId.matches.($matches.1))
        {
            $req = $requestId.matches += @{$matches.1 = "RequestId-$($requestId.count)"}
            $requestId.count++
            $req.keys | %{ Add-Content $tmp "$_ : $($req.$_)" }
        }
        $_ -replace $matches.1,$requestId.matches.($matches.1)               
    }
    'keyId>(\w{70})</' {
        if(!$keyId.matches.($matches.1))
        {
            $kid = $keyId.matches += @{$matches.1 = "keyId-$($keyId.count)"} 
            $keyId.count++
            $kid.keys | %{ Add-Content $tmp "$_ : $($kid.$_)" }
        }
        $_ -replace $matches.1,$keyId.matches.($matches.1)        
    }
    'reportId>(\w{19})</msg:reportId>' {
        if(!$reportId.matches.($matches.1))
        {
            $repid = $reportId.matches += @{$matches.1 = "Report-$($reportId.count)"}
            $reportId.count++
            $repid.keys | %{ Add-Content $tmp "$_ : $($repid.$_)" }
        }
        $_ -replace $matches.1,$reportId.matches.($matches.1)
    } 
    default {$_}
}

$output | Set-Content $log -Encoding UTF8

Get-Content $log
Get-Content $tmp

【问题讨论】:

  • 存储用于 PoSh 的数据结构的常用方法是使用 Export/Import-CliXml cmdlet。另一种是使用 JSON ......但 CliXml 的东西是为保存和恢复 PoSh 对象的完整结构而设计的。
  • 您能告诉我们您用于&lt;keyId&gt; 标签的正则表达式模式吗?听起来你可能不小心截断了它
  • 请在您的问题中添加minimal reproducible example
  • 问题已更新为相关代码。另一个问题是如果同一行上有 2 个匹配的字符串 - 仅更新第一个字符串,第二个保持不变,脚本继续到下一行。如何避免这种情况?

标签: powershell hashtable


【解决方案1】:

如果您不关心找到它们的顺序(如果您不想重复,我假设您不会关心),只需在最后将它们全部导出即可。我仍然会将它们保留在“对象”形式中,以便您可以轻松导入/导出它们。 CSV 将是数据的理想候选者。

$requestId,$keyid,$reportid | Foreach-Object {
    foreach($key in $_.matches.keys)
    {
        [PSCustomObject]@{
            Original    = $key
            Replacement = $_.matches.$key
        }
    }
}

这个例子的数据输出到控制台

Original                                                               Replacement
--------                                                               -----------
qwerty-qwer12-qwer56                                                   RequestId-1
zxcvbn-zxcv12-zxcv56                                                   RequestId-2
1234qw-12qw12-12qw56                                                   RequestId-3
Qwd84lPhjutf7Nmwr56hJndcsjy34imNQwd84lPhjutZ7Nmwr56hJndcsjy34imNPozDr5 keyId-1    
Zdjgi76Gho3sQw0ib5Mjk3sDyoq9zmGdZdjgi76Gho3sQw0ib5Mjk3sDyoq9zmGdLkJpQw keyId-2    
poGd56Hnm9q3Dfer6Jh                                                    Report-1   
plmkjh8765FGH4rt6As                                                    Report-2  

只需将其输入Export-Csv

$requestId,$keyid,$reportid | Foreach-Object {
    foreach($key in $_.matches.keys)
    {
        [PSCustomObject]@{
            Original    = $key
            Replacement = $_.matches.$key
        }
    }
} | Export-Csv $tmp -NoTypeInformation

【讨论】:

    猜你喜欢
    • 2021-09-28
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多