Textmustererkennung mit Ruby

Was sind reguläre Ausdrücke

Reguläre Ausdrücke beschreiben Textmuster

Alltagsbeispiel: rm *.exe

  • sed
  • grep
  • Perl
  • libpcre

Ruby syntax

bomb Language 'ruby' not supported


   text = "Lemma 1:\tDer Rechenbetrieb laeuft normal"   


   # regexe stehen zwischen Schrägstrichen:
   #  =~ vergleicht einen Text mit einem regulären Ausdruck:
   if text =~ /trieb/
     puts "Treffer"
   end


   # Negation:
   puts "Nix gefunden" if text !~ /nicht/


   # erzeugt ein Regexp object:
   muster = /trieb/
   

   # Text und Regexp haben beide eine Methode 'match',
   #  der Effekt ist der Gleiche
   puts "Nicht dasselbe" unless text.match(muster) == muster.match(text)
   puts "aber das Gleiche" if text.match(muster).to_s == muster.match(text).to_s

   # Ohne Treffer gibts nil
   puts text.match(/hadelfadel/)

   # %r ist eine Alternative zu /../ die beliebige Klammerungszeichen erlaubt:
   %r°/usr/bin/°.match(`which ruby`) and puts "Ruby wohnt in /usr/bin"
   # oder so:
   %r{/usr/bin/}.match(`readlink -f $(which perl)`) and puts "Perl wohnt direkt daneben"


   # Variablen in Mustern benutzen:
   substr = "mal"
   muster = / nor#{substr}/
   puts text.match(muster)   


   # Textanfang und -ende werden als ^ und $ angegeben:
   puts text.match(/^betrieb/) # nicht am Anfang des Textes
   puts text.match(/normal$/)  # das klappt

   ### Zeichenklassen

   selbstlaute = /[aeiou]/
   puts text.match(selbstlaute)

   ## Metazeichen in Zeichenklassen
   
   # Negation mit ^
   mitlaute = /[^aeiou]/
   puts text.match(mitlaute)

   # Bereiche mit -
   mitlaute = /[b-df-hj-np-tv-z]/
   puts text.match(mitlaute)

     # Einschub: Modifier
     kleinbuchstaben = /[a-z]/
     grossbuchstaben = /[A-Z]/

     buchstaben = /[a-zA-Z]/
     # /.../i vergleicht ohne Unterscheidung von Groß- und Kleinschreibung:
     buchstaben = /[a-z]/i

   # Es geht noch kürzer:
   ziffer = /\d/      # == /[0-9]/
 
   weissraum = /\s/   # == /[ \t\n]/ (Leerzeichen, Tabulator und Zeilenvorschub (newline),
                      #   außerdem eigentlich auch Wagenrücklauf (carriage return, \r) 
                      #   und Seitenvorschub (formfeed, \f)

   wortzeichen = /\w/ # == /[a-zA-Z0-9_]/ (plus Buchstaben fremder Alphabete)

   # und die Umkehrung
   nicht_ziffer  = /\D/ # == [^\d]
   dunkelraum    = /\S/ # == [^\s]
   unwortzeichen = /\W/ # == [^\w]

   # und natürlich noch der Punkt:

   beliebiges_zeichen = /./ # Außer newline!


      # Einschub: mehrzeiliger Text
      mehrzeiliger_text = "Erste Zeile\n2. Zeile\nLetze Zeile"

      puts mehrzeiliger_text.match(/.\d/)  # nil
      puts mehrzeiliger_text.match(/.\d/m) # "\n2" - Wichtiger Unterschied zu Perl!
      # \A und \Z und die Unterschiede zu ^ und $ ...


   ## Disjunktionen (Oder-Verknüpfungen):

   # oft ist es hilfreich, auf Wortanfang oder -ende zu prüfen:
   wortgrenze    = /\w\W|\W\w/ # == /\w\W/ 'oder' /\W\w/
   print "Wortgrenze: '",text.match(wortgrenze),"'\n"

   # Dafür gibt es aber den Anker \b:
   wortgrenze    = /\b/ # fast wie /\w\W|\W\w/, 'verbraucht' aber keine Zeichen!

   # Leer - Muster überprüft nur, ob der Text Wort-Nichtwort-Übergänge enthält:
   print "Wortgrenze: '",text.match(wortgrenze),"'\n" 

   wortgrenze    = /.\b./ # == /\w\W|\W\w/
   print "Wortgrenze: '",text.match(wortgrenze),"'\n"

   # Disjunktionen (Oder-Verknüpfungen) in Mustern:
   artikel = /Der|Die|Das|der|die|das/ # /der|die|das/i würde auch dER erkennen ...

   # Gruppieren:
   artikel = /[Dd](er|ie|as)/ # so klappt's


   # Treffer in Klammern extrahieren:
   if text =~ /^Lemma (\d): / 
      puts "Text ist Lemma Nr. #{$1}"
   end

   ## Wiederholungen erkennen
   
   # * erkennt 0 und mehr Wiederholungen des vorhergehenden Musters:

   muster = /.*/ # passt auf den kompletten Text, selbst wenn dieser leer ist:

   "" =~ muster and puts "Treffer von .* für ''"

   # + erkennt ein oder mehr Wiederholungen des vorhergehenden Musters:
   muster = /.+/ 

   "" =~ muster or puts "Kein Treffer von .+ für ''"
   
   langes_wort = /\w{8,}/
   puts text.match(langes_wort)

   nicht_so_langes_wort = /\w{6,10}/
   puts text.match(nicht_so_langes_wort)

   # Mist, Wortgrenze vergessen:
   nicht_so_langes_wort = /\b\w{6,10}\b/
   if text.match(nicht_so_langes_wort)
     puts $~     # enthält das in der vorigen Zeile erzeugte MatchData 
                 #  Object ohne explizite Zuweisung
   else
     puts "Kein Wort zwischen 6 und 10 Buchstaben gefunden"
   end
   
   muster = /(\d{1,3}\.){3}\d{1,3}/
   puts `gethostip shaller.gsi.de`.match(muster)

   # ? erkennt 0 oder 1 Vorkommen des vorhergehenden Musters:   
   puts text.match(/laeuft (nicht )?normal/)


   ## Gieriges ('greedy') Matching:
   # Quantifizierer wirken immer so weit wie möglich:
 
   muster = /R.*\s/
   puts text.match(muster)

   # das kann man mit einem angehängten Fragezeichen umkehren
   muster = /R.*?\s/
   puts text.match(muster)

   # Analog: (muster)??, (muster)+?, (muster){n,m}?

   ## Textersetzung

   # Kein s/../../ ???

   # Ersetzt durch String.sub
   puts text.sub(/(laeuft) (normal)/,'\1 nicht \2')

   # s/../../g ist String.gsub:

   puts text.gsub(/r/i,"'")

   # mit String.scan erhält man alle Vorkommen eines Musters als Liste
   #  jedoch ohne Überlappungen:
   puts text.scan(/\w{4}/).join(", ")

   # mit String.split kann man einen Text mithilfe von Mustern zerteilen
   puts text.split(/\s[A-Z]/).join(" | ")


Links

-- ChristopherHuhn - 26 Nov 2010
Topic revision: r1 - 2010-11-26, ChristopherHuhn
 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding GSI Wiki? Send feedback
Imprint (in German)
Privacy Policy (in German)