powershell使用正则表达式数组从一个文件中获取内容,并替换另一个文件中的内容



我知道一些编程基础知识,但这个项目远远超出了我的知识范围。任何帮助都将是非常感激的,提前谢谢你。

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

$file = "C:powershellchangescriptAdd.bat"

文件Add.bat:

@Echo Off
cd %systemroot%system32
Reg.exe add "HKCUSoftwareHPHPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "ModelName" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "HostName" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "IP Address" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "SerialNo" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "Services" /t REG_SZ /d "PclPrint eSCL LEDM" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "MAC" /t REG_SZ /d "tochange" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "GUID" /t REG_SZ /d "tochange" /f
xcopy "C:applicationsTwainConfig*" "%USERPROFILE%AppDataLocal" /s /i /Y
Cls
Exit
$filemin = "C:powershellchangescriptpc.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:powershellchangescriptpc.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:powershellchangescriptAddScan.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 "HKCUSoftwareHPHPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "ModelName" /t REG_SZ /d "HP Color LaserJet Pro M478fxxx" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "HostName" /t REG_SZ /d "EPxxxxxx" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "IP Address" /t REG_SZ /d "192.x.x.x" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "SerialNo" /t REG_SZ /d "CNBxx3P8WY" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "Services" /t REG_SZ /d "PclPrint eSCL LEDM" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "MAC" /t REG_SZ /d "c4651645xxb95" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "GUID" /t REG_SZ /d "urn:uuid:8866a4ce-2da1-5b24-6af5-13e5dc7f63b5" /f
xcopy "C:applicationsTwainConfig*" "%USERPROFILE%AppDataLocal" /s /i /Y
Cls
Exit

你可以用下面的代码来解决这个问题:

((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 "HKCUSoftwareHPHPTwain" /v "DesktopShortcut" /t REG_SZ /d "Yes" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "ModelName" /t REG_SZ /d "HP Color LaserJet Pro M478fxxx" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "HostName" /t REG_SZ /d "EPxxxxxx" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "IP Address" /t REG_SZ /d "192.x.x.x" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "SerialNo" /t REG_SZ /d "CNBxx3P8WY" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "Services" /t REG_SZ /d "PclPrint RestScan eSCL LEDM Fax" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "NetworkType" /t REG_SZ /d "Ethernet" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "MAC" /t REG_SZ /d "c4651645xxb95" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "Manufacturer" /t REG_SZ /d "Hewlett-Packard" /f
Reg.exe add "HKCUSoftwareHPHPTwain" /v "GUID" /t REG_SZ /d "urn:uuid:8866a4ce-2da1-5b24-6af5-13e5dc7f63b5" /f
xcopy "C:applicationsTwainConfig*" "%USERPROFILE%AppDataLocal" /s /i /Y
Cls
Exit

regex101 forpc.txt文件。

regex101 forAdd.bat文件。

这样做的一种方法是读取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:Testpc.txt' -Raw) -replace '(?m)^(.*?):','$1=' | ConvertFrom-StringData
# read the 'Add.bat' as string array
$bat = (Get-Content -Path 'D:TestAdd.bat') | ForEach-Object {
if ($_ -match '^Reg.*/vs+"([^"]+)".*"(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:TestNew.bat' -PassThru

结果:

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

Regex细节:

^                 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