regexp zum Zaehlen von Buchstaben

R

rikola

Foren Gott
Hallo,

ich wuesste gerne den regulaeren Ausdruck (fuer grep o.ae.), um Zeilen aus einer Textdatei auszuwaehlen, die einen bestimmten Buchstaben hoechstens n-mal enthalten (nicht unbeding hintereinander)

Ich moechte zum Beispiel aus der Datei
Code:
eeeee
eee
awdeeftge
aefgesde
werwet
flhlkghk
efefefefefef
nur die Zeilen haben, die hoechstens 3 'e' enthalten, also in diesem Beispiel alle ausser der ersten und der letzten.

Danke sehr.
 
Hi,

das erinnert mich an meine Klausur theoretische Informatik, lang lang ist's her... Wie ging das doch gleich? Ahja, das laesst sich mit einem finite state automaton sehr leicht modeln (sorry, ich kenne den deutschen Fachausdruck nicht).
Du nimmst 4 states, und bleibst in jedem state genau so lange bis du ein "e" antriffst. Das laesst sich dann sehr leicht in eine regexp umwandeln.
Hier mal ohne eine konkrete Syntax zu verwenden:
Code:
[A-DF-Za-df-z]*e[A-DF-Za-df-z]*e[A-DF-Za-df-z]*e[A-DF-Za-df-z]*

Das sollte es tun.

Edit:
Eh, fuer Gross- und Kleinbuchstaben natuerlich entsprechend anpassen, ich sehe grade dass jetzt nur kleine "e"s gematcht werden, aber das duerfte ja bekannt sein wie das funktioniert. ;)

mfg,
bytepool
 
Zuletzt bearbeitet:
[A-DF-Za-df-z]*e[A-DF-Za-df-z]*e[A-DF-Za-df-z]*e[A-DF-Za-df-z]*
Passt dieser Ausdruck nicht auch dann, wenn davor oder danach noch weitere e's kaemen? Zumindest filtert grep bei Deinem Ausdruck nicht die erste oder letzte Zeile aus.
 
Hi,

das sollte eigentlich nicht passieren, nein. Schliesslich schliesst du das e explizit aus ([A-DF-Za-df-z]), und sagst dass es genau dreimal vorkommen darf.

Allerdings ist das auch ein ungetestetes theoretisches Konstrukt, es koennte sein dass es fuer die Praxis mit einem konkreten regexp System noch leicht angepasst werden muss.

Wenn grep das unterstuetzt koenntest du mal versuchen die Anzahl der einzelnen e's auf genau eins festzulegen (meistens mit e{1}).

Edit:
Ach, natuerlich gibt dir grep die Zeile aus. Der Ausdruck kommt ja in der Zeile vor, hatte kurzzeitig verdraengt was grep macht...
D.h. du muesstest noch explizit festlegen dass davor und danach nichts mehr sein darf, z.B. mit den Ankern ^ und $.

Edit2:
Eventuell laesst sich der Ausdruck sogar noch weiter verallgemeinern und vereinfachen:
Code:
^[^e]*e[^e]*e[^e]*e[^e]*$
;)

mfg,
bytepool
 
Zuletzt bearbeitet:
Ist doch traurig hier, nix mit finite state machine, nix mit regexp, einfach nur "tr" Operator in perl:
Code:
$ echo -e 'e,e,eee\nebe\nesse\nsesambroetchen\neeee\nfoo'|
perl -ne 'print if tr/e/e/ <= 3'

tr/// in skalarem Kontext (der durch's if-Konstrukt gegeben ist) gibt einfach die Anzahl der "matches" zurück. (tr arbeitet nicht mit regulären Ausdrücken.)

edit: hupsale, es wurde ja explizit nach einer RE gefragt, dann vereinfache ich doch einfach mal die vom bytepool:
Code:
^([^e]*e){3}[^e]*$
(Sollte afaik exakt das Selbe sein. (Oder das Gleiche? kA))
Aber für sowas Regexes zu nutzen ist doch auch wieder traurig, aber naja.
 
Zuletzt bearbeitet:
Danke an beide. Auch perl war prima, mir kam nur nicht in den Sinn, dass es ohne regexp funktionieren koennte.
Die regexp von Gott_in_schwarz funktioniert bei mir allerdings nicht (wohl der perl-Ausdruck).
 
Ich hab den ja auch nur durch Klammerung syntaktisch minimiert. Der Ausdruck matcht halt genau Zeilen mit N (die Zahl in den kräuseligen Klammern ({})) e's. Nicht mehr und nicht weniger.
Da du aber höchstens sagtest, muss man aus der {3} eine {0,3} (sprich: 0 bis 3 mal) machen:
Code:
echo -e 'e,e,eee\nebe\nesse\nsesambroetchen\neeee\nfoo'|
perl -ne 'print if /^(?:[^e]*e){0,3}[^e]*$/'
Aber wie du siehst sind regexes für sowas eher ungeeignet.

edit: oder auch mit egrep:
Code:
echo -e 'e,e,eee\nebe\nesse\nsesambroetchen\neeee\nfoo'|
egrep '^([^e]*e){0,3}[^e]*$'
 

Ähnliche Themen

bash: Fehlermeldung und Werte in Array sortieren?

Zeile an txt anhängen

Server-Monitoring mit RRDTool

Zurück
Oben