我是新编程人员,我正在尝试改进脚本的以下代码,我正考虑制作一个函数来对其进行改进,但我不知道从哪里开始或它是否是最佳选择。
$replaceText01 = (Get-Content -path $copyFileLocation -Raw) -replace '"INSTANCENAME="TEST""',$NUEVAINESTANCIA
Set-Content $copyFileLocation $replaceText01
$replaceText02 = (Get-Content -path $copyFileLocation -Raw) -replace '"INSTANCEID="TEST""',$NUEVAINESTANCIAID
Set-Content $copyFileLocation $replaceText02
$replaceText03 = (Get-Content -path $copyFileLocation -Raw) -replace "NT Service\SQLAgent#TEST", $CUENTAAGTN
Set-Content $copyFileLocation $replaceText03
$replaceText04 = (Get-Content -path $copyFileLocation -Raw) -replace "NT Service\MSSQL#TEST", $CUENTASQLSER
Set-Content $copyFileLocation $replaceText04
$user = "$env:UserDomain\$env:USERNAME"
write-host $user
$replaceText = (Get-Content -path $copyFileLocation -Raw) -replace "##MyUser##", $user
Set-Content $copyFileLocation $replaceText
答案 0 :(得分:1)
首先,我可能会尝试仅读取一次文件。然后,由于您正在执行许多类似的操作,因此我将所有与操作有关的数据放入一个数组中,然后遍历这些数据。
在这段代码中,我首先读取了文件。然后,我定义了所有应该替换的字符串以及应该替换它们的字符串。然后,我使用循环来遍历数据,以便我们不会一直重复相同的代码。
$data = Get-Content -Path $copyFileLocation -Raw
$replacements = @(
@('"INSTANCENAME="TEST""', $NUEVAINESTANCIA),
@('"INSTANCEID="TEST""', $NUEVAINESTANCIAID),
@("NT Service\SQLAgent#TEST", $CUENTAAGTN),
@("NT Service\MSSQL#TEST", $CUENTASQLSER),
@("##MyUser##", "$env:UserDomain\$env:USERNAME")
)
$replacements | ForEach-Object {
$data = $data.Replace($_[0], $_[1])
}
Set-Content -Path $copyFileLocation -Value $data
如果您使用管道而不是将数据分配给变量,也有可能使它更短
$data = Get-Content -Path $copyFileLocation -Raw
@(
@('"INSTANCENAME="TEST""', $NUEVAINESTANCIA),
@('"INSTANCEID="TEST""', $NUEVAINESTANCIAID),
@("NT Service\SQLAgent#TEST", $CUENTAAGTN),
@("NT Service\MSSQL#TEST", $CUENTASQLSER),
@("##MyUser##", "$env:UserDomain\$env:USERNAME")
) | ForEach-Object {
$data = $data.Replace($_[0], $_[1])
}
Set-Content -Path $copyFileLocation -Value $data
编辑:错过了您在询问如何使其成为函数的问题。
通过查看您的操作,我假设您正在修改SQL无人值守安装文件,并已如此命名。
这里的一个好主意是使大多数参数成为强制性的,因此可以确保用户至少指定了所有必需的参数。也许您以后想指定MyUser
,因此这是具有默认值的参数的理想选择。
Function Set-SQLInstallFileVariables {
Param(
[Parameter(Mandatory)][string]$FilePath,
[Parameter(Mandatory)][string]$NUEVAINESTANCIA,
[Parameter(Mandatory)][string]$NUEVAINESTANCIAID,
[Parameter(Mandatory)][string]$CUENTAAGTN,
[Parameter(Mandatory)][string]$CUENTASQLSER,
[string]$MyUser = "$env:UserDomain\$env:USERNAME"
)
$data = Get-Content -Path $FilePath -Raw
@(
@('"INSTANCENAME="TEST""', $NUEVAINESTANCIA),
@('"INSTANCEID="TEST""', $NUEVAINESTANCIAID),
@("NT Service\SQLAgent#TEST", $CUENTAAGTN),
@("NT Service\MSSQL#TEST", $CUENTASQLSER),
@("##MyUser##", $MyUser)
) | ForEach-Object {
$data = $data.Replace($_[0], $_[1])
}
Set-Content -Path $copyFileLocation -Value $data
}
答案 1 :(得分:0)
首先要注意的是,每次替换时都要反复读写文件,这不是很有效。 这是不需要的。一旦读取,内容就在字符串变量中,并且可以在写回文件之前在内存中进行多次操作。
一种方法是使用包含搜索和替换字符串的字符串数组。 为了使它正常工作,两个数组必须具有相同数量的元素。
$inputFile = 'D:\Test\TheFile.txt' # your input file path here ($copyFileLocation)
$outputFile = 'D:\Test\TheReplacedFile.txt' # for safety create a new file instead of overwriting the original
$searchStrings = '"INSTANCENAME="TEST""','"INSTANCEID="TEST""',"NT Service\SQLAgent#TEST","NT Service\MSSQL#TEST","##MyUser##"
$replaceStrings = $NUEVAINESTANCIA, $NUEVAINESTANCIAID, $CUENTAAGTN, $CUENTASQLSER, "$env:UserDomain\$env:USERNAME"
# get the current content of the file
$content = Get-Content -path $copyFileLocation -Raw
# loop over the search and replace strings to do all replacements
for ($i = 0; $i -lt $searchStrings.Count; $i++) {
$content = $content -replace [regex]::Escape($searchStrings[$i]), $replaceString[$i]
}
# finally, write the updated content to a (new) file
$content | Set-Content -Path $copyFileLocation
另一种方法是使用同时存储搜索字符串和替换字符串的Hashtable
:
$inputFile = 'D:\Test\TheFile.txt' # your input file path here ($copyFileLocation)
$outputFile = 'D:\Test\TheReplacedFile.txt' # for safety create a new file instead of overwriting the original
$hash = @{
'"INSTANCENAME="TEST""' = $NUEVAINESTANCIA
'"INSTANCEID="TEST""' = $NUEVAINESTANCIAID
"NT Service\SQLAgent#TEST" = $CUENTAAGTN
"NT Service\MSSQL#TEST" = $CUENTASQLSER
"##MyUser##" = "$env:UserDomain\$env:USERNAME"
}
# get the current content of the file
$content = Get-Content -path $copyFileLocation -Raw
# loop over the items in the hashtable to do all replacements
$hash.GetEnumerator() | ForEach-Object {
# the `$_` is an automatic variable you get within a ForEach-Object{}
# It represents a single item on each iteration.
$content = $content -replace [regex]::Escape($_.Key), $_.Value
}
# finally, write the updated content to a (new) file
$content | Set-Content -Path $copyFileLocation
在两种情况下,我们都使用-replace
,这是不区分大小写的正则表达式替换。因为您的搜索字符串包含在正则表达式中有特殊含义的字符(#
和\
),所以我们需要使用[regex]::Escape()
希望有帮助
答案 2 :(得分:0)
这是我的尝试。它并不意味着要精益。而是要真正弄清楚它在做什么,同时又要充满功能(太多),并阻止您多次获取内容。
看到其他人回答后,他们的代码更好。希望我的代码易于阅读,并为您提供有关使用管道和函数的更好的主意:)
Function Replace1 {Process{$_ -replace '"INSTANCENAME="TEST""',$NUEVAINESTANCIA}}
Function Replace2 {Process{$_ -replace '"INSTANCEID="TEST""',$NUEVAINESTANCIAID}}
Function Replace3 {Process{$_ -replace "NT Service\SQLAgent#TEST", $CUENTAAGTN}}
Function Replace4 {Process{$_ -replace "NT Service\MSSQL#TEST", $CUENTASQLSER}}
Function Replace6 {Process{$_ -replace "##MyUser##", $user}}
$user = "$env:UserDomain\$env:USERNAME"
Write-Host $user
Get-Content -path $copyFileLocation | Replace1 | Replace2 | Replace3 | Replace4 | Replace5 | Replace6 | Set-Content -path $copyFileLocation