Je suis une nouvelle programmation, j'essaye d'améliorer le code suivant d'un script, je pensais faire une fonction pour l'améliorer mais je ne sais pas par où commencer ni si c'est la meilleure option.
$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
3 Réponses :
Tout d'abord, j'essaierais probablement de lire le fichier une seule fois. Ensuite, puisque vous effectuez de nombreuses opérations similaires, je mettrais toutes les données sur les opérations dans un tableau, puis j'effectuerais une itération sur ces données.
Dans ce code, je lis d'abord le fichier. Ensuite, je définis toutes les chaînes qui doivent être remplacées avec les chaînes qui doivent les remplacer. Ensuite, j'utilise une boucle pour parcourir les données afin de ne pas répéter le même code tout le temps.
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
}
Il est également possible de raccourcir encore plus si vous utilisez le pipeline au lieu d'assigner les données à une variable
$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
Edit: Vous avez manqué que vous demandiez comment en faire une fonction.
En regardant à ce que vous faites, je suppose que vous modifiez un fichier d'installation SQL sans assistance et que vous l'avez nommé comme tel.
Une bonne idée ici est de rendre la plupart des paramètres obligatoires, donc vous êtes sûr que l'utilisateur au moins spécifie tous les paramètres requis. Peut-être souhaitez-vous spécifier MyUser plus tard, c'est donc un bon candidat pour être un paramètre avec une valeur par défaut.
$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
Oops. J'ai manqué ça. Je vais en faire une fonction.
Une chose à mentionner ici est que .Replace () est une méthode sensible à la casse. L'OP peut ne pas s'en rendre compte et pourrait faire en sorte que la fonction manque sur certains remplacements.
La première chose à noter est que vous lisez et écrivez le fichier encore et encore à chaque remplacement, ce qui n'est pas très efficace. Ce n'est pas nécessaire; une fois lu, le contenu est dans une variable de chaîne et peut être manipulé en mémoire plusieurs fois avant de réécrire dans le fichier.
Une approche consiste à utiliser des tableaux de chaînes qui contiennent les chaînes de recherche et de remplacement. Pour que cela fonctionne correctement, les deux tableaux doivent avoir le même nombre d'éléments.
$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
Une autre approche consisterait à utiliser un Hashtable qui stocke à la fois le les chaînes de recherche et les chaînes de remplacement:
$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
Dans les deux cas, nous utilisons -replace , qui est un remplacement de regex insensible à la casse. Parce que vos chaînes de recherche contiennent des caractères qui ont une signification particulière dans les expressions régulières ( # et \ ), nous devons les échapper avec [regex] :: Escape () code>
J'espère que cela aide
Voici ma tentative. Ce n'est pas censé être maigre. Plutôt que d'être vraiment clair sur ce qu'il fait tout en étant plein de fonctions (trop) et en vous empêchant d'obtenir le contenu plusieurs fois.
Après avoir vu ce que tout le monde a répondu, leur code est meilleur. J'espère que le mien est lisible et vous donnera une meilleure idée de l'utilisation du pipeline et des fonctions :)
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