2

Part of some text file (pfile.ora) looks like this:

fubar.__db_cache_size=1040187392
fubar.__pga_aggregate_target=1291845632
*.audit_file_dest='C:\app\oracle\admin\fubar\adump'
*.db_recovery_file_dest='\\nas3\backup\SRV07\fast_recovery_area\fubar'
*.db_recovery_file_dest_size=42949672960
*.dispatchers='(PROTOCOL=TCP) (SERVICE=fubarXDB)'

In that file, 1 parameter needs to be updated. I found this function somewhere to read and parse the file:

function Parse-IniFile ($file) {
   $ini = @{}
   switch -regex -file $file {
      "^\s*([^#].+?)\s*=\s*(.*)" {
         $name,$value = $matches[1..2]
         $ini[$name] = $value.trim()
      }
   }
   $ini
}

The result is stored in variable $aLines:

$aLines = Parse-IniFile ('pfile.ora');

After updating the parameter:

$aLines.'*.db_recovery_file_dest' = "'\\nas4\backup\SRV07\fast_recovery_area\fubar'";

... displaying the contents of $aLines results in:

Name                              Value
----                              -----
*.db_recovery_file_dest          '\\nas3\backup\SRV07\fast_recovery_area\fubar'
fubar.__db_cache_size            1040187392
fubar.__pga_aggregate_target     1291845632
*.audit_file_dest                'C:\app\oracle\admin\fubar\adump'
etc...

The elements are all completely unordered! I need them ordered as they were. After:

$sOut = "";
foreach($oLine in $aLines.GetEnumerator() ) {
   $sOut += $oLine.name + "=" + $oLine.value +"`r`n";
}

and writing $sOut to file no line is at its original location anymore.

Long story, simple question: how do I get the result back as it was, still being able to easily change one of the parameters?

Any help would be greatly appreciated!

Erik
  • 135
  • 1
  • 6

2 Answers2

1

Since all you want to do is modify a single line, I'd drop the function altogether and simply do something like this:

$file     = '.\pfile.ora'
$key      = [regex]::Escape('*.db_recovery_file_dest')
$newValue = '\\nas4\backup\SRV07\fast_recovery_area\fubar'

(Get-Content $file) -replace "($key=).*","`$1$newValue" | Out-File $file
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • This is definitely the shortest solution I could ask for and it works shockingly well. Thx. – Erik Sep 05 '13 at 21:08
0

Since you are storing the original entries in a hashtable, the original ordering is lost and based on the hashtable's internal hashing algorithm. I think the simplest solution is to cache the original order when parsing the file and then use that when outputting.

So change your parsing function like this:

function Parse-IniFile ($file) {
   $ini = @{}
   $fields = @() # to store the order
   switch -regex -file $file {
      "^\s*([^#].+?)\s*=\s*(.*)" {
         $name,$value = $matches[1..2]
         $ini[$name] = $value.trim()
         $fields += $name
      }
   }
   $ini,$fields
}

Now when you call the function you will have to store each returned object in a separate variable like this:

$aLines,$fields = Parse-IniFile .\pfile.ora

After you make your edit, you can output in the original order using the $fields variable:

$fields | foreach{"$_=$($aLines[$_])"}
zdan
  • 28,667
  • 7
  • 60
  • 71