Umgang mit case-sensitiven ini-Dateien

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Umgang mit case-sensitiven ini-Dateien

19 Aug 2016, 14:22

Ist ein Weg vorstellbar, wie man mit case-sensitiven Ini-Dateien umgehen könnte? Ich habe z. B. dieses Abkürzungsverzeichnis, das ich gerne als ini-Datei einsetzen würde. Das Verzeichnis enthält jedoch zahlreiche gleichnamige Einträge, die sich nur in der Groß-/Kleinschreibung unterscheiden, z. B.
Ehem=Ehemann
ehem=ehemalig
ErbSch=Erbschein
Erbsch=Erbschaft
Wie kann man damit ggf. umgehen? Gibt es einen Weg oder ist ein Weg vorstellbar?
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Umgang mit case-sensitiven ini-Dateien

20 Aug 2016, 01:58

Moin,

hast Du schon ausprobiert, wie sich INI-Dateien in diesem Fall verhalten?

Wenn das nicht klappt, könnte ein (case-sensitives) Dictionary Object interessant sein. Deine Abkürzungen kannst Du dann als einfache Textdatei oder als #Include vorhalten.

Letzlich bleibt noch die Holzfällermethode: Textdatei einlesen und parsen.
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Umgang mit case-sensitiven ini-Dateien

20 Aug 2016, 12:54

@just me, vielen Dank!
Ich glaube, Du hast recht, dass man das wirklich nur mit der "Holzhackermethode" lösen kann. Eigentlich ist es nicht recht nachvollziehbar, warum Windows den Umgang mit ini-Dateien nur caseinsensitiv vorsieht. Das wäre doch echt mal ein Feature, mit dem Windows zeigen könnte, dass dort logisch weitergedacht wird. Ich habe das jetzt holzhackermäßig mit FileRead, StringCaseSense On, Loop, Parse und == gelöst:

Code: Select all

; Ermittelt einen casesensitiven Ini-String, hilfsweise einen normalen Inistring.
GetIniStringEx(Dateiname, Sektion, Gesucht) {
   ; Sucht zunächst vorrangig nach der buchstabengetreuen Schreibweise:
   StringCaseSense On ; Stellt die case-sensitive Suche ein
   SuBegr  := Gesucht . "=" ; Suchbegriff mit Gleichheitszeichen
   Länge   := StrLen(SuBegr) ; Länge des Suchbegriffs incl. Gleichheitszeichen
   FileRead, Ini, %Dateiname% ; Liest die Datei in den Arbeitsspeicher
   TInhalt := StrLen(Sektion)>0 ? ini_getSection(ini, Sektion) : ini ; zu ini_getSection() vgl. https://autohotkey.com/board/topic/116561-lib-ini-v10-basic-ini-string-functions
   Loop, Parse, TInhalt, `n, `r
   {
      If (SubStr(A_LoopField, 1, Länge)==SuBegr) ; Wenn die passende Zeile gefunden wurde
      {
         Gefunden := A_LoopField
         Break
      }
   }
   ; Schlußbehandlung:
   If (StrLen(Gefunden)>0) ; Entnimmt die zweite Stelle hinter dem Gleichheitszeichen
      Gefunden := StrSplit(Gefunden, "=").2
   Else If (StrLen(Sektion)>0) ; sucht hilfsweise nach der caseinsensitiven Schreibweise
      IniRead, Gefunden, %Dateiname%, %Sektion%, %Gesucht%, %A_Space%
   Return Trim(Gefunden)
}
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Umgang mit case-sensitiven ini-Dateien

21 Aug 2016, 02:29

Hallo Johnny R.,

im Fall eines Abkürzungsverzeichnisses, das - wie ich annehme - nur gelesen wird, finde ich ein Dictionary recht praktisch. Du kannst das dann als einfache Textdatei mit einem Paar pro Zeile speichern und musst nicht auf die Begrenzungen von INI-Dateien achten. Das könnte dann so aussehen:

Code: Select all

#NoEnv
SetBatchLines, -1

AbkDat := "
(Join`r`n
Ehem=Ehemann
ehem=ehemalig
ErbSch=Erbschein
Erbsch=Erbschaft
)"

AbkDict := CreateDictionary(AbkDat)

For Key In AbkDict
   MsgBox, 0, Eintrag #%A_Index%, % Key . " = " . AbkDict.Item(Key)

MsgBox, 0, Abfrage auf 'Test', % "Test = " . AbkDict.Item("Test") ; liefert nichts

ExitApp

CreateDictionary(ByRef KeyValPairs, KeySep := "=", PairSep := "`r`n") {
   ; KeyValPairs  -  Schlüssel-Wert-Paare
   ; KeySep       -  Trennzeichen zwischen Schlüssel und Wert
   ; PairSep      -  Trennzeichen zwischen den Paaren
   ; Scripting.Dictionary -> autohotkey.com/boards/viewtopic.php?p=396#p396
   SD :=	ComObjCreate("Scripting.Dictionary")
   KSLen := StrLen(KeySep)
   For Each, Pair In StrSplit(KeyValPairs, PairSep, " ")
      If (P := InStr(Pair, KeySep))
         SD.Add(Trim(SubStr(Pair, 1, P - 1)), Trim(SubStr(Pair, P + KSLen)))
   Return SD
}
Die Funktion ini_getSection() ist mittlerweile eingebaut: IniRead, AusgabeVarSektion, Dateiname, Sektion. Sie liefert allerdings maximal 65.533 Zeichen.
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Umgang mit case-sensitiven ini-Dateien

21 Aug 2016, 12:51

@just me, vielen Dank!
Ich habe jetzt Deine Dictionary-Lösung verbaut und meine Lösung entsorgt. Das Dictionary-Objekt kannte ich noch nicht. Und schon habe ich wieder etwas hinzugelernt. Kann man sehr gut als Ersatz für ini-Dateien verwenden. Danke!

Gibt es eigentlich eine Möglichkeit, derartige Objekte zu speichern, um sie später im Bedarfsfall einfach wieder herzustellen oder müssen solche Objekte immer wieder von Grund auf neu aufgebaut werden?
User avatar
Micromegas
Posts: 260
Joined: 28 Apr 2015, 23:02
Location: Germany

Re: Umgang mit case-sensitiven ini-Dateien

28 Sep 2023, 09:56

Johnny R wrote:
20 Aug 2016, 12:54
[…] dass man das wirklich nur mit der "Holzhackermethode" lösen kann. […]
Es gibt auch eine ❀Blumenpflückerinnenmethode❀: In der INI-Datei zu Großbuchstaben ein sonst wenig gebrauchtes Zeichen hinzufügen, und dieses vor dem Aufruf von IniRead ersetzen. Zum Beispiel ein ^ voranstellen. Oder, was mir aus verschiedenen Gründen lieber ist, ein . Für deutsche Abkürzungen sollte es die RegEx ([A-ZÄÖÜ])(?=.*=)ᐞ$1 tun. (Das habe ich jetzt gerade von RegEx-QuickRef abgeschrieben und noch nicht getestet. Im Unterschied zum nachfolgenden Skript habe ich hier nur eine Klasse mit deutschen großen Umlauten eingetragen; zum einen, um mit einer bekannteren Alternative zu beginnen, und zum anderen, damit die Ersetzung auch mit Editoren, die dabei weniger können als AHK, durchgeführt werden kann.)

Damit sähe die INI-Datei etwa so aus:

Code: Select all

ᐞEhem=Ehemann
ehem=ehemalig
ᐞErbᐞSch=Erbschein
ᐞErbsch=Erbschaft
und das Skript etwa so:

Code: Select all

SuBegr_mit_Zusatzzeichen := RegExReplace(SuBegr,"(\p{Lu})", "ᐞ$1")
IniRead Gefunden, %Dateiname, % Sektion, % SuBegr_mit_Zusatzzeichen
Auch nach der caseinsensitiven Schreibweise, wie in Johnny R's Code, kann man suchen, wenn man danach einfach noch die folgenden Zeilen anhängt:

Code: Select all

if (Gefunden = "ERROR")
	IniRead Gefunden, %Dateiname, % Sektion, % SuBegr
(Damit das auch für Suchbegriffe, für die die Liste keine völlig kleingeschriebene Variante hat, funktioniert, muss man dann noch solche einfügen, etwa so:

Code: Select all

erbsch=Erbschaft oder Erbschein (uneindeutige Abk.)
)

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 35 guests