Home > Software design >  Manipulate text file - change multiple lines
Manipulate text file - change multiple lines

Time:04-07

Have been looking at what I thought would be a really simple task this morning.... and turns out it wasn't, at least not for me.

What I am trying to do is get powershell to read through an ini-file, and change multiple values under specific headers only.

[Datoformat]
Separator=.
[Database]
Path=servername:d:\mycompany\nextsys_db\next.fdb
DokumentDbPath=
FireBird25=Nei

[Pictures]
Path=T:\nextsys_bilde
DbExtractFolder=

[Brukerinnstillinger]
Prioriter=Ja
�pneJournalAuto=Nei
TillatBrukerBytte=Ja
EnkelJournal=Nei
AvtBokRadHoyde=
AvtBokMndKolonneBredde=
Resepsjonsmaskin=Nei
Tilgangsoversikt=Nei
AvtaleHentPasientAutomatisk=Ja
VisFargeForAnsvarlig=Nei
[Eksport]
Automatisk=Nei
[Import]
Automatisk=Nei
[Skjerm]
HuskSkjermPosisjon=Ja
ProgramSkjermPosX=-8
ProgramSkjermPosY=-8
ProgramSkjermBredde=1936
ProgramSkjermHoyde=1056
MaksimertSkjermPosisjon=Ja
EgenDefSkjermSizeX=1919
EgenDefSkjermSizeY=1080
UtvidetAvtalebok=Ja
UtvidetJournal=Ja
UtvidetRecall=Ja
UtvidetOmsetning=Ja
UtvidetUtestaaende=Ja
UtvidetRegnskap=Ja
UtvidetFakturaOversikt=Ja
UtvidetGenerelleModuler=Ja
UtvidetAlleModuler=Ja
1280800=Nei
1440900=Nei
16801050=Nei
19201080=Nei
Egendefinert=Ja
AutomaticSize=Nei
[Spesialinnstillinger]
EnForekomst=Nei
TestModusInfo=Nei
AktiverRegningskortJournalSjekk=Nei
IkkeSpmOmHelseskjema=Nei
IkkeSpmOmBrukerBytteAvtale=Nei
IkkeSpmOmBrukerBytteAnsvarlig=Nei
[Vedlegg]
Path=
[Avtalebok]
Utseende=
Bakgrunn=
[Journal]
JournalTextSize=8
JournalTextFont=
JournalTextStyle=
FetSkrift=Nei
[Rontgen]
AlternativAapning=Nei
[Utseende]
IkkeVisDagensPasienter=Nei
[MediLink]
BenyttMediLink=Nei
AutomatiskInnlesing=Nei
MediLinkInnlesingIntervall=
[AutomatiskOppdatering]
VedOppstart=Nei
Alltid=Nei
FraLokaltNettverk=Nei
NettverkPath=
UtenBekreftelse=Nei
[BankTerminal]
PosPay=Nei
BetTermAlwaysOn=Ja
BBSFlerBrukerTerminal=Nei
ThisMerchantHighest=Nei
MerchantId=
TerminalId=
BrukerBoPosDrivere=Nei
BrukerBaxiDrivere=Ja
BaxiAktiverXReport=Ja
BaxiAktiverZReport=Nei
BaxiAktiverReversal=Nei
[EasyPanel]
Benytt=Nei
Notat=Nei
Diagnose=Nei
Epikriser=Nei
Sykemelding=Nei
Resept=Nei
Henvisning=Nei
Helseskjema=Nei
Endo=Nei
Perio=Nei
Bilder=Nei
Tekn.skjema=Nei
Skjema=Nei
Dokumentmodul=Nei
[Oppstartsbilde]
VisesVedOppstart=Nei
[Printer]
LokaltOppsett=Ja
TryktA5Resept=Nei
TryktA5ReseptDesign2=Nei
TimeKortKvittSkriver=Nei
VisMinimalBaxInfo=Nei
ReseptKvittSkriver=Nei
JusteringVenstreMargX=
JusteringToppMargY=
Faktura=HP LaserJet Pro MFP M125-M126 PCLmS
Recallkort=HP LaserJet Pro MFP M125-M126 PCLmS
Timekort=HP LaserJet Pro MFP M125-M126 PCLmS
Kvittering=HP LaserJet Pro MFP M125-M126 PCLmS
Resept=HP LaserJet Pro MFP M125-M126 PCLmS
Standard=HP LaserJet Pro MFP M125-M126 PCLmS
Tekniker=HP LaserJet Pro MFP M125-M126 PCLmS
FakturaStorrelse=A4
RecallKortStorrelse=A4
TimekortStorrelse=A4
KvitteringStorrelse=A4
ReseptStorrelse=A4
TeknikerStorrelse=A4
StandardStorrelse=A4
FakturaOppsettKode=
RecallkortOppsettKode=
TimekortOppsettKode=
KvitteringOppsettKode=
ReseptOppsettKode=
TeknikerOppsettKode=
StandardOppsettKode=
FakturaPapirretning=St�ende
RecallKortPapirretning=St�ende
TimekortPapirretning=St�ende
KvitteringPapirretning=St�ende
ReseptPapirretning=St�ende
TeknikerPapirretning=St�ende
StandardPapirretning=St�ende
FakturaPreview=Ja
RecallKortPreview=Ja
TimekortPreview=Ja
KvitteringPreview=Ja
ReseptPreview=Ja
TeknikerPreview=Ja
StandardPreview=Ja
[Paaminnelse]
Automatisk=Nei
AutomatiskService=Nei
Tidspunkt=
Dagens=Nei
KunMerketOnsker=Nei
AutomatiskEpost=Nei
AntallDagerFrem=Nei
AntallDagerFremAntall=2
ErstattTekst=Nei
PaaminnelseTekst=Hei [fornavn], minner om time reservert til deg: [dato] kl. [tid]. Timer  som ikke passer m� avbestilles senest 24 timer i forveien.  Mvh.  [tittel] [brukernavn]  
[SMS]
Testmodus=Nei
VisAdvarslerVedIkkeSendtSMS=Nei
[Innlogging]
TillatInnloggingMedEldreProgramversjonEnnDatabase=Nei

I want to change the values "Automatisk=Nei" to "Automatisk=Ja", "Tidspunkt=" to "Tidspunkt=10:00" and "AntallDagerFrem=Nei" to "AntallDagerFrem=Ja"... The Tidspunkt and AntallDagerFrem values shouldn't be that hard since they only appear once in the file, but "Automatisk=Nei" appears 4 times, and I only want to change the one below [Paaminnelse]

$content = @(if ((Get-Content $inifile) -join "`n" -match '\[Paaminnelse\]([\s\S]*)\[SMS\]') { $Matches[1] }) 

$newcontent = $test -replace  'Automatisk=Nei','Automatisk=Ja' -replace 'Tidspunkt=','Tidspunkt=10:00' -replace 'AntallDagerFrem=Nei','AntallDagerFrem=Ja'

This finds the correct lines from the ini-file and changes the values I want to change, but using Set-Content $inifile -Value $newcontent will of course remove all everything else from the file which is not what I want :)

More used to cat, grep, awk and sed than PowerShell to be honest so any pointers would be helpful.

CodePudding user response:

As Theo notes, consider using a dedicated INI file parser, such as the one provided by the third-party PsIni module - see this answer for how to install and use it.

  • Update: Your own answer now shows how to use it to solve your specific problem.

If installing a module isn't an option, I suggest using a -switch statement, which has awk-like capabilities:

# Array of sample lines, as would be returned by:
#   Get-Content $inifile
$iniFileLines = @'
[Datoformat]
Separator=.

[Eksport]
Automatisk=Nei

[Paaminnelse]
Automatisk=Nei
AutomatiskService=Nei
Tidspunkt=

[Printer]
AutomatiskEpost=Nei
AntallDagerFrem=Nei
AntallDagerFremAntall=2
'@ -split '\r?\n'

$inPaaminnelseSect = $false

# Note: To operate directly on your file, replace 
#       ($iniFileLines) with -File $iniFile
switch -Regex ($iniFileLines) {
  '^(Tidspunkt)=$' { '{0}=10:00' -f $Matches[1]; continue }
  '^(AntallDagerFrem)=Nei' { '{0}=Ja' -f $Matches[1]; continue }
  '^(Automatisk)=Nei' { 
    if ($inPaaminnelseSect) { '{0}=Ja' -f $Matches[1] } else { $_ }; continue 
  }
  '^\[(. )\]' { $inPaaminnelseSect = $Matches[1] -eq 'Paaminnelse'; $_ }
  default { $_ } # pass through
}

Note:

  • The above assumes:

    • that your file has exactly the format as shown in your question. However, it would be easy to make parsing more flexible with respect to optional whitespace.

    • that you only want to replace entries if they have a specific current value (or none); this too could easily be changed to replace the values irrespective of the current value.

  • Matching is case-insensitive, as PowerShell generally is by default; add the -CaseSensitive switch to make it case-sensitive.

Output:

[Datoformat]
Separator=.

[Eksport]
Automatisk=Nei

[Paaminnelse]
Automatisk=Ja
AutomatiskService=Nei
Tidspunkt=10:00

[Printer]
AutomatiskEpost=Nei
AntallDagerFrem=Ja
AntallDagerFremAntall=2

CodePudding user response:

Theo and mklement0 have both pointed to the PsIni-module which does exactly what I wanted to do - so consider the question answered.

Set-IniContent $inifile -Sections 'Paaminnelse' -NameValuePairs @{
  Automatisk='Ja'; Tidspunkt='10:00'; AntallDagerFrem='Ja'
} | Out-IniFile $inifile -Force
  • Related