Link to home
Start Free TrialLog in
Avatar of JasonLattin
JasonLattin

asked on

Powershell "out-file" command write blank file.

I have a powershell script that opens an XML document. Reads each line. Modifies specific ones based on some values it receives. Then writes the lines back changed/unchanged as needed. I think the logic works because I have some "write-host" entries that display what is going on in the code.

But when the script finished the orignal file "c:\tempxyz\test.txt" is completely blank. The script has completely erased everything. I'm not sure where I have gone wrong.

Below is my script and ***samples of the output and the @@@ source test.txt file
-------------------------------------------

cls
$Filename = "c:\tempxyz\test.txt"

write-host -foregroundcolor "yellow" "Are you switching from :"
write-host "A = Training To Prod
write-host "B = Prod To Training

$ProdOrPreview = read-host "Choice A or B? "

(Get-Content $Filename) | Foreach-Object {            
      $TrimmedLine=$_.trim() #(Takes "$_" and removes the leading spaces
      If ($TrimmedLine.StartsWith("<JobName>")) {
            $a = $TrimmedLine -match "<\w+>(.*?)</\w+>"
            $JobName = $Matches[1]
            write-host "JobName is $JobName"
            }
      If ($TrimmedLine.StartsWith("<DrawerName>")) {
            if ($ProdOrPreview -eq 'B') {$Drawername = "Training"}
            if ($ProdOrPreview -eq 'A') {$Drawername = $JobName}
            $_ = "<DrawerName>"+$DrawerName+"</DrawerName>" #formats line to be re-written back into test.txt
            write-host "   Writing to file $_" #lets user know what got written into test.txt
            }
      } | out-file $FileName



--------------------------------------------------

*** Here is what outputs on the screen when I run it :
--------------------------------------------------
Are you switching from :
A = Training To Prod
B = Prod To Training
Choice A or B? : B

JobName is Commercial
   Writing to file <DrawerName>Training</DrawerName>
JobName is Personal
   Writing to file <DrawerName>Training</DrawerName>

-------------------------------------------------------

@@@ Below is sample test.txt file before it is edited
-------------------------------------------------------
    <MappingJobConfiguration>
                  <JobName>Commercial</JobName>
      <LocationName />
                 <DrawerName>Commercial</DrawerName>
    </MappingJobConfiguration>
    <MappingJobConfiguration>
                  <JobName>Personal</JobName>
      <JobDescription>Personal</JobDescription>
      <LocationName />
                   <DrawerName>Personal</DrawerName>
SOLUTION
Avatar of becraig
becraig
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of JasonLattin
JasonLattin

ASKER

@BECRAIG...
I tried the "-append" suggestion. No fix. Same blank output.

i suspect it is line 11 that messesus up. I commented out  8-13 and the script runs without changing anything. I think my alterations to "$_" goofs it up somehow. But I can't be sure. Just a gut feeling.
Here is the ultimate goal :
If the $ProdOrPreview variable is "A" then it reads through the file and replaces every "<DrawerName>???</DrawerName>" value with ""<DrawerName>Training</DrawerName>"

If the $ProdOrPreview variable is "b" then it reads through the file and replaces every "<DrawerName>???</DrawerName>" value with ""<DrawerName>JobName</DrawerName>"
$jvar = @()
$Filename = "testfile.txt"
$file2 = "tesout.txt"

write-host -foregroundcolor "yellow" "Are you switching from :"
write-host "A = Training To Prod"
write-host "B = Prod To Training"

$ProdOrPreview = read-host "Choice A or B? "
(Get-Content $Filename) | Foreach-Object {            
      $TrimmedLine=$_.trim() 
      If ($TrimmedLine.StartsWith("<JobName>")) {
            $a = $TrimmedLine -match "<\w+>(.*?)</\w+>"
            $JobName = $Matches[1]
            write-host "JobName is $JobName"
            }
      If ($TrimmedLine.StartsWith("<DrawerName>")) {
            if ($ProdOrPreview -eq 'B') {$Drawername = "Training"}
            if ($ProdOrPreview -eq 'A') {$Drawername = $JobName}
            $jvar += "<DrawerName>"+$DrawerName+"</DrawerName>`n"
            #formats line to be re-written back into test.txt
            write-host "   Writing to file $_" 
            #lets user know what got written into test.txt
            }
      } 

      $jvar | out-file $Filename

Open in new window

@BECRAIG..
i tried your code and it gets us closer. It does write the changed lines. but that is all it writes. It doesn't have all of the other data from the file.

This is what the test.txt lookslike after your script... it is missing the rest of the data.
---------------
<DrawerName>Commercial</DrawerName>

<DrawerName>Personal</DrawerName>
@BECRAIG
i am so thankful for your help.
I ran your new code and it still only writes the lines that it changes. it isn't writing the lines that it doesn't alter. I end up with a file with only two lines in it. you are on the right track. Just missing something...

Results :
<DrawerName>Training</DrawerName>
<DrawerName>Training</DrawerName>

It should look like :
<MappingJobConfiguration>
                  <JobName>Commercial</JobName>
      <LocationName />
                 <DrawerName>Training</DrawerName>
    </MappingJobConfiguration>
    <MappingJobConfiguration>
                  <JobName>Personal</JobName>
      <JobDescription>Personal</JobDescription>
      <LocationName />
                   <DrawerName>Training</DrawerName>
In general, here's the basic structure of the script where I've done things like this in the past:
(Get-Content $Filename) | Foreach-Object {
    If (condition)
    { $_ -replace "something","somethingelse" }
    ElseIf (othercondition)
    { $_ -replace "othersomething","othersomethingelse" }
    Else
    { $_ }
} | Out-File $Filename

Open in new window

If I get a chance this afternoon I'll modify your code unless becraig has already come up with the solution.
@footech.
your code would work but my content varies. i won't know what the find/repalce values are in advance.

Based on @BECRAIG I think my issue is I need to be doing a write-output for every line.
Right now it only does it for the one I change.
I'll modify my if statement to write the modified line if it changes, if not write the original.
@BECRAIG...
I used your idea and built a nested IF/ELSe loop that seems to be doing the trick. Let me test it a little bit and then i'll reward you the points. your "write-output" was they key I was missing.
Try this, on line 24:
} else {$jvar += $TrimmedLine}
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
OK... I'm not sure where BECRAIG's comment went, but earlier he found that I wasn't sending anytything out the pipe so I had to change my "wrtite-host" lines to "write-output". He also correctly identified that I needed to do a write-output even on lines that i don't alter. I built a nested IF/ELSE statement that does a write-output for all lines, even the ones I didn't alter.
It worked perfectly.
Instead of modifying all the code, you could of just added the else like I said.
If you wanted to keep the spaces:
} else {$jvar += $_}
Yeah that was my comment about not sending to the pipeline.  Deleted it because the code I posted wasn't complete.  But I'm glad it helped you out.
OK... I'm not sure where BECRAIG's comment went, but earlier he found that I wasn't sending anytything out the pipe so I had to change my "wrtite-host" lines to "write-output". He also correctly identified that I needed to do a write-output even on lines that i don't alter. I built a nested IF/ELSE statement that does a write-output for all lines, even the ones I didn't alter.
It worked perfectly.