【问题标题】:powershell get content from one file using array of regex and replace content within another filepowershell 使用正则表达式数组从一个文件中获取内容并替换另一个文件中的内容
【发布时间】:2021-10-10 07:10:13
【问题描述】:

我知道一些编程基础知识,但这个项目远远超出了我的知识范围。任何帮助将不胜感激,在此先感谢您。

有两个带有文本的文件(见下文),我需要检查第一个文件(正则表达式)并使用预定义的模式数组替换另一个文件中的文本。 这是代码和文本文件的示例,这样我会更容易理解我需要什么。

 $file = "C:\powershell\changescript\Add.bat"

Add.bat 文件内容:

@Echo Off
cd %systemroot%\system32
Reg.exe add "HKCU\Software\HP\HPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "ModelName" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "HostName" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "IP Address" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "SerialNo" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Services" /t REG_SZ /d "PclPrint eSCL LEDM" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "MAC" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "GUID" /t REG_SZ /d "tochange" /f
xcopy "C:\applications\TwainConfig\*" "%USERPROFILE%\AppData\Local\" /s /i /Y
Cls
Exit

 $filemin = "C:\powershell\changescript\pc.txt"

文件pc.txt的内容:

ModelName       : HP Color LaserJet Pro M478fxxx
HostName        : EPxxxxxx
IP Address      : 192.x.x.x
SerialNo        : CNBxx3P8WY
Services        : PclPrint RestScan eSCL LEDM Fax
MAC             : c4651645xxb95
GUID            : urn:uuid:8866a4ce-2da1-5b24-6af5-13e5dc7f63b5

  

这不起作用,但描述了我需要的东西(至少我认为它描述了..)

$filemin = "C:\powershell\changescript\pc.txt"
      $findThisAndReplace = @(
            $paternchange1 = '"ModelName" /t REG_SZ /d "tochange" /f"',
            $paternchange2 = '"HostName" /t REG_SZ /d "tochange" /f"',
            $paternchange3 = '"IP Address" /t REG_SZ /d "tochange" /f"',
            $paternchange4 = '"SerialNo" /t REG_SZ /d "tochange" /f"',
            $paternchange5 = '"MAC" /t REG_SZ /d "tochange" /f"',
            $paternchange6 = '"GUID" /t REG_SZ /d "tochange" /f"'
            )
            $file = "C:\powershell\changescript\AddScan.bat"
      $replaceWith = @(
            $paternget1 = '"ModelName       : *',
            $paternget2 = '"HostName        : *',
            $paternget3 = '"IP Address      : *',
            $paternget4 = '"SerialNo        : *',
            $paternget5 = '"MAC             : *',
            $paternget6 = '"GUID            : *'
            )
    function getsetcontent ($patern, $filemin, $file){
    $i=0;
    while $1 !> 7
    do
    (get-content $file) | ForEach-Object {$i++;$_ -Replace $patternchange$i, "$paternget$i"} | Set-Content -Encoding UTF8 $filemin}
    
    

合并后的结果应该是:

@Echo Off
cd %systemroot%\system32
Reg.exe add "HKCU\Software\HP\HPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "ModelName" /t REG_SZ /d "HP Color LaserJet Pro M478fxxx" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "HostName" /t REG_SZ /d "EPxxxxxx" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "IP Address" /t REG_SZ /d "192.x.x.x" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "SerialNo" /t REG_SZ /d "CNBxx3P8WY" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Services" /t REG_SZ /d "PclPrint eSCL LEDM" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "MAC" /t REG_SZ /d "c4651645xxb95" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "GUID" /t REG_SZ /d "urn:uuid:8866a4ce-2da1-5b24-6af5-13e5dc7f63b5" /f
xcopy "C:\applications\TwainConfig\*" "%USERPROFILE%\AppData\Local\" /s /i /Y
Cls
Exit

【问题讨论】:

  • 不错的任务规范。你都尝试了些什么?你目前被困在哪里?
  • 嘿,我一直在从这个文件中获取模式 $filemin = "C:\powershell\changescript\pc.txt" 。并将它们放在数组中

标签: arrays regex powershell file


【解决方案1】:

您可以使用以下代码解决您的问题:

((Get-Content pc.txt) -replace '^([^:]+):', '$1=' | Out-String | ConvertFrom-StringData).GetEnumerator() | ForEach-Object -Process { New-Variable -Name $_.key -Value $_.Value -Force }
$ExecutionContext.InvokeCommand.ExpandString(((Get-Content Add.bat) -replace '("([^"]+)"[^"]+)"tochange"', '$1"${$2}"' | Out-String)) | Set-Content AddNew.bat -PassThru

结果:

@Echo Off
cd %systemroot%\system32
Reg.exe add "HKCU\Software\HP\HPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "ModelName" /t REG_SZ /d "HP Color LaserJet Pro M478fxxx" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "HostName" /t REG_SZ /d "EPxxxxxx" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "IP Address" /t REG_SZ /d "192.x.x.x" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "SerialNo" /t REG_SZ /d "CNBxx3P8WY" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Services" /t REG_SZ /d "PclPrint RestScan eSCL LEDM Fax" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "MAC" /t REG_SZ /d "c4651645xxb95" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "GUID" /t REG_SZ /d "urn:uuid:8866a4ce-2da1-5b24-6af5-13e5dc7f63b5" /f
xcopy "C:\applications\TwainConfig\*" "%USERPROFILE%\AppData\Local\" /s /i /Y
Cls
Exit

regex101 用于 pc.txt 文件。

regex101 用于 Add.bat 文件。

【讨论】:

  • 问题是这个文件是由另一个脚本生成的: $comp=$args[0] echo $comp $logFile = "c:\temp\$comp.txt" $open = "\\ $comp\c$\temp\$comp.txt" Invoke-Command -ComputerName $comp -ScriptBlock { $SID = (New-Object -ComObject Microsoft.DiskQuota).TranslateLogonNameToSID((Get-WmiObject –ComputerName $Using:comp -类 Win32_ComputerSystem).Username) $list = Get-ItemProperty 注册表::HKEY_USERS\$($SID)\SOFTWARE\HP\HPtwain | Where-Object {$_ -Match "HostName"} |输出文件 $Using:logFile }
  • @filbrinza,好的,让我们保持原样:) 查看我的更新答案。
  • 谢谢(正则表达式规则)
【解决方案2】:

这样做的一种方法是读取带有注册表值名称和替换字符串的pc.txt,并将其转换为易于使用的哈希表。

然后逐行遍历您的 .bat 文件并进行更改:

# organize the values from 'pc.txt' into a Hashtable
# read the file as single multiline string and replace the first colon (:)
# of every line into an equals sign (=). 
# then use ConvertFrom-StringData to obtain a Hashtable
$pcHash = (Get-Content -Path 'D:\Test\pc.txt' -Raw) -replace '(?m)^(.*?):','$1=' | ConvertFrom-StringData
# read the 'Add.bat' as string array
$bat = (Get-Content -Path 'D:\Test\Add.bat') | ForEach-Object {
    if ($_ -match '^Reg.*/v\s+"([^"]+)".*"(tochange)"') {
        if ($pcHash.ContainsKey($matches[1])) {
            # output this line updated
            $_ -replace $matches[2], $pcHash[$matches[1]]
        }
    }
    else {
        # output the line unchanged
        $_
    }
}

# output to (new) file. -PassThru will also show the result on screen
$bat | Set-Content -Path 'D:\Test\New.bat' -PassThru

结果:

@Echo Off
cd %systemroot%\system32
Reg.exe add "HKCU\Software\HP\HPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "ModelName" /t REG_SZ /d "HP Color LaserJet Pro M478fxxx" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "HostName" /t REG_SZ /d "EPxxxxxx" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "IP Address" /t REG_SZ /d "192.x.x.x" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "SerialNo" /t REG_SZ /d "CNBxx3P8WY" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Services" /t REG_SZ /d "PclPrint eSCL LEDM" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "MAC" /t REG_SZ /d "c4651645xxb95" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCU\Software\HP\HPTwain" /v "GUID" /t REG_SZ /d "urn:uuid:8866a4ce-2da1-5b24-6af5-13e5dc7f63b5" /f
xcopy "C:\applications\TwainConfig\*" "%USERPROFILE%\AppData\Local\" /s /i /Y
Cls
Exit

正则表达式详细信息:

^                 Assert position at the beginning of the string
Reg               Match the characters “Reg” literally
.                 Match any single character that is not a line break character
   *              Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
/v                Match the characters “/v” literally
\s                Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   +              Between one and unlimited times, as many times as possible, giving back as needed (greedy)
"                 Match the character “"” literally
(                 Match the regular expression below and capture its match into backreference number 1
   [^"]            Match any character that is NOT a “"”
      +           Between one and unlimited times, as many times as possible, giving back as needed (greedy)
) 
"                 Match the character “"” literally               
.                 Match any single character that is not a line break character
   *              Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
"                 Match the character “"” literally
(                 Match the regular expression below and capture its match into backreference number 2
   tochange       Match the characters “tochange” literally
)
"                 Match the character “"” literally

【讨论】:

  • 您的解决方案非常有效。而且非常优雅。一个小问题是我得到: PSPath : Microsoft.PowerShell.Core\Registry::HKEY_USERS\S-1-5-21-1414065607-2312316 653-3939627664-20885\SOFTWARE\HP\HPtwain PSParentPath : Microsoft.PowerShell.Core \Registry::HKEY_USERS\S-1-5-21-1414065607-2312316 653-3939627664-20885\SOFTWARE\HP PSChildName : HPtwain PSProvider : Microsoft.PowerShell.Core\Registry 这行在我的第一个脚本中也是如此,它破坏了你的正则表达式。我知道没有在第一时间发布它是我自己的错。
  • 问题已通过在我的原始脚本中添加“Select-Object * -exclude PSPath,PSParentPath, PSChildName, PSProvider, PSDrive”得到解决,再次感谢,非常感谢。
猜你喜欢
  • 1970-01-01
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
  • 2019-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
相关资源
最近更新 更多