Wortanzahl und Lesezeit

Wer Texte schreibt kennt die Herausforderung: Wortwiederholungen vermeiden, wie lang ist der Text, wie lange dauert etwa das lesen. Das lässt sich per Autohotkey-Skript herausfinden.

Wer mit Markdown-Editoren schreibt, bekommt z.B. in Caret wahlweise die Wortzahl oder eine Lesezeit angezeigt. Auf welcher Grundlage die ermittelt wird, ist unklar. Ich kenne keinen Editor, der Auskunft über die Wiederholungsrate von Worten eines Textes gibt. Weil ich bei den Editoren aufgrund wechselnder Anforderungen mäandere, wäre natürlich eine vom Editor unabhängige Lösung praktisch.

Dass diese Anforderung andere ebenfalls antreibt, zeigt Fefes Blog, der sich gleich diverse Lösungen entwickelte. Ein Eintrag im Autohotkey-Foum sucht genau dafür eine Lösung. Der Beitrag von „derRaphael“ war für mich ein guter Anfang. Ich habe den Ansatz„aufgebohrt“, damit es meine Anforderung erfüllt:

  • Zählen von markiertem Text
  • Lesezeit ermitteln
  • (zusammenhängende) Zahlen werden als Wort gezählt
  • Wortwiederholungen ermitteln

Die Zahlen sind ein (kleines) Problem, weil Autohotkey beim unterscheiden größerer Zahlen Probleme hat. Die Lösung ist trivial: per „Textverkettung“ werden grundsätzlich Worte statt Zahlen verglichen. Die Wortwiederholungen zählen löste das Script zwar, allerdings hat es alle einzelnen Worte angezeigt, womit der Dialog bei einem umfangreicheren Text unhandlich und unübersichtlich wurde. Außerdem ließ es die Variablen unaufgeräumt im Speicher zurück, was zu falschen Ergebnissen führt, wenn das Skript als Teil einer Funktionssammlung verwendet wird (mein Anwendungsfall).

Zwecks besserer Verständlichkeit des Skripts sind die Variablen „klingender“ benannt und die Kommentare angepasst. Dir Originalität des Urhebers (s.o.) soll damit keinesfalls verschleiert werden.

; ---------------------- Worte zählen
; Grundlage:
; http://ahkscript.org/germans/forums/viewtopic.php?t=4023&sid=9bd455d2df662c8b038311ada3d0e0d6
; Erweiterungen: Gezählt wird markierter Text, Zahlen werden mitgezählt, Gesamtwörterzahl, Lesezeit, 
; nur Wiederholungen auflisten, formatierte Ausgabe, Variablen leeren, Aufruf über ALT WIN W
 
!#w:: 
; Zwischenablage sichern und leeren
CBackup := ClipboardAll
Clipboard =
; Markierten Text in die Zwischeanblage ziehen, Warten bis alles drin ist
SendInput, ^c
ClipWait 0
; Wenn nichts selektiert ist, ist die Zwischenablage leer → keine Zählung, Zwischenablage wiederherstellen, Ende
 If ErrorLevel
   {
      MsgBox, 16, Wortzähler, Kein Text ausgewählt!`nWortzählung abgebrochen.
      Clipboard := CBackup
      return
   }
; Klemmbrett-Inhalt in reinen Text konvertieren, falls HTML, o.ä.
Txt = %Clipboard%
; Zwischenablage wieder herstellen, Variable freigeben/leeren
Clipboard := CBackup
CBackup =
; alles AUSSER Leerzeichen, a bis z, Umlaute und sz (groß + klein wo angebracht)
; 0 bis 9 entfernen und durch Leerzeichen ersetzen (negiert durch ^ am Gruppenanfang)
 Txt := RegExReplace(txt,"[^ a-zA-ZöäüÖÄÜß0-9]"," ")
   ; Mehrfache leerzeichen und Zeilenumbrüche durch ein Leerzeichen ersetzen
Txt := RegExReplace(txt,"(\n|\s)+"," ")
  ; Zeilenanfang-/ende bereinigen (Wagenrücklauf, Leerzeichen)
Txt := RegExReplace(txt,"\r|^\s+|\s+$")
  ; Wort­- und Textliste erzeugen
 Wortliste := Textliste := RegExReplace(txt,"\s","`n")
; Wortliste ohne Doubletten erzeugen
Sort,Wortliste,U
 ; Summenzähler initialisieren
Summe := 0
; Wortliste durchlaufen
Loop, Parse, Wortliste,`n
{
  ; bearbeitete Zeile (=Inhalt von Variabe A_LoopField) kopieren
   A_Current := A_LoopField                  
  ; Wortzähler initialisieren
   A_Count := 0         
 ; Wortliste durchlaufen und gleiche Worte zählen, 
 ; "S" . … (Zeichen beliebig) sorgt dafür, dass Zahlen als Text verglichen werden (64-Bit Grenze überschritten oder Autokonversion von z.B. Hex in Int verhindern)
   Loop,Parse,Textliste,`n                               
 { 
    if (("S" . A_Current ) = ("S" . A_LoopField))  
         A_Count++                                                           
  }
   ; „Häufigkeitsvariable“ Anzahlx anlegen und/oder Wort mit dieser Häufigkeit anhängen
   Anzahl%A_Count% .= ((StrLen(Anzahl%A_Count%)>1) ? ", " : "") A_Current
   ; Ergebnisliste anlegen/erweitern
   Zaehlung .= ((A_Index>1) ? "`n" : "") A_Count         
   ; Häufigkeit in die Gesamtsumme übernehmen
   Summe += A_Count  
}
; Anzahl und Lesezeit ausgeben, Mittelwert 200 Worte/Minute als Berechnungsgrundlage
Resultat :=   Summe . " Worte, Lesezeit ca. " .   Floor(Summe/200) . "'" .  Round(Mod(Summe,200)/200*60,0)  . """ (200W/Min.)`n`nWortwiederholungen `n"
; Häufigkeit absteigend sortieren
Sort,Zaehlung,NUR                                         
; Ausgabe formatieren, nur Wortwiederholungen ausgeben, „Häufigkeitsvariablen“ freigeben
Loop,Parse,Zaehlung,`n                                    
{
     if A_LoopField > 1 
     {
        Resultat .= ((A_Index>1) ? "`n" : "") "→ " Format("{:3i}",A_LoopField) "x " Anzahl%A_LoopField% 
     }
    Anzahl%A_LoopField%=
  } 
MsgBOx ,  64 , Wortzählung, %Resultat%
; Variablen leeren/freigeben, damit Nutzung in Funktionssammlungen korrekt funktioniert
Textliste=
Wortliste=
Zaehlung=
Resultat=
Return