I'm encountering a basic issue when writing the following PowerShell script and using loops and branching. It appears that I'm missing something very simple here, but right now I don't understand how to improve the script.
So here is an example:
$mycsv = Import-Csv mycsv.csv
for ($i = 1 ; $i -le 123 ; $i ) {
$currentvalue = "OLD"
foreach ($value in $mycsv) {
switch ($value.oldValue) {
$currentvalue {
Write-Host "Number $i - $currentvalue replaced with $($value.newValue)"
}
default { Write-Host "Number $i - $currentvalue unchanged" }
}
}
}
mycsv.csv file has the following three lines:
oldValue,newValue
FOO,BAR
OLD,NEW
ABC,DEF
And the current output is as follows:
...
Number 123 - OLD unchanged
Number 123 - OLD replaced with NEW
Number 123 - OLD unchanged
...
As you can see, for each number the script writes three lines. This is expected because the script has the foreach
loop for the three entries in the CSV file.
But I want the script to display a status of the operation, not a status of matching each entry's oldValue to newValue.
What do I need to change in the script to make it display either the "unchanged" string or the "replaced" string? Do I need to add break
somewhere to make the script exit the foreach
loop? Or do I need to replace foreach
with something else?
PS I understand that my script does not actually replace anything now. It just displays output based on $currentvalue and entries in the CSV file.
Update #1
I'm trying to Write-Host
different text based on the $currentvalue
and rows in mycsv.csv
. If the script finds the value of $currentvalue
in the first column of mycsv.csv
, then it has to write "Number 1 - OLD replaced with NEW" where NEW is taken from the same row of the CSV file ($value.newValue).
You can think of it as if I'm using the CSV file as a reference. If e.g., the script parses a text file and finds the word OLD, it needs to replace it with the word NEW taken from the CSV.
I've attempted to simplify my script and leave only relevant parts. It has a little bit more code, but I intentionally left it out because it's not important in context of this question.
I was intending to use foreach
to loop through the entries in the CSV file and match them with $currentvalue
. When $currentvalue
matches one of the entries in the first column of CSV, the script needs to write "Number 1 - (word taken from the first column) replaced with (word taken from the second column)".
If there are no matches, then the script should write "Number 1 - $currentvalue unchanged".
So there should be only two types of output:
"Number 1 - (word taken from the first column) replaced with (word taken from the second column)" (if there is a match)
"Number 1 - $currentvalue unchanged" (if no matches found)
The for
loop is required by the script because it has to iterate though revision numbers. I'm passing $i
to a command-line utility. I left this part of the script out because its not important here IMO.
CodePudding user response:
Given this test Csv:
$csv = @'
oldValue,newValue
FOO,BAR
OLD,NEW
ABC,DEF
BAZ,BAZ
'@ | ConvertFrom-Csv
What I believe you want:
$csv | ForEach-Object { $idx = 1 } {
$status = 'unchanged'
if($_.oldValue -ne $_.newValue) {
# if it changed assign a new value
$status = 'replaced with {0}' -f $_.newValue
}
Write-Host ('Number {0} - {1} {2}' -f $idx , $_.oldValue, $status)
}
Which would output:
Number 1 - FOO replaced with BAR
Number 2 - OLD replaced with NEW
Number 3 - ABC replaced with DEF
Number 4 - BAZ unchanged
What I believe you should do instead is take an object oriented approach:
$csv | ForEach-Object {
$status = 'unchanged'
if($_.oldValue -ne $_.newValue) {
# if it changed assign a new value
$status = 'replaced with {0}' -f $_.newValue
}
# output a new object appending this new property
$_ | Select-Object *, @{ N='Status'; E={ $status }}
}
Which would output:
oldValue newValue Status
-------- -------- ------
FOO BAR replaced with BAR
OLD NEW replaced with NEW
ABC DEF replaced with DEF
BAZ BAZ unchanged