Ich versuche, einen regulären Ausdruck zu schreiben, in dem alle Wörter mit einer Länge von 10 Zeichen angezeigt werden und keiner der Buchstaben wiederholt wird.
Bisher habe ich bekommen
grep --colour -Eow '(\w{10})'
Welches ist der allererste Teil der Frage. Wie würde ich nach der "Einzigartigkeit" suchen? Ich habe wirklich keine Ahnung, ansonsten muss ich Rückverweise verwenden.
grep
regular-expression
Dylan Meeus
quelle
quelle
Antworten:
schließt Wörter mit zwei identischen Zeichen aus.
schließt diejenigen aus, die sich wiederholende Zeichen haben.
POSIXly:
tr
sFügt Wörter in eine eigene Zeile ein, indem alle Gleichungen von Nicht-Wort-Zeichen ( cAuslassung von alphanumerischen Zeichen und Unterstrichen) in Zeilenumbrüche umgewandelt werden.Oder mit einem
grep
:(Ausgenommen sind Zeilen mit weniger als 10 und mehr als 10 Zeichen sowie Zeilen mit mindestens zweimal vorkommenden Zeichen.)
Mit
grep
nur einem (GNU grep mit PCRE-Unterstützung oderpcregrep
):Das heißt, eine Wortgrenze (
\b
) gefolgt von einer Folge von 10 Wortzeichen (vorausgesetzt, auf jedes folgt keine Folge von Wortzeichen und sich selbst, unter Verwendung des negativen Look-Ahead-PCRE-Operators(?!...)
).Wir sind froh, dass es hier funktioniert, da nicht viele reguläre Ausdrücke mit Rückverweisen in sich wiederholenden Teilen arbeiten.
Beachten Sie, dass (mit meiner Version von GNU grep mindestens)
Funktioniert nicht, aber
does (as
echo aa | grep -Pw '(.)\2'
) was wie ein Bug klingt.Du möchtest vielleicht:
wenn Sie wollen ,
\w
oder einen\b
beliebigen Buchstaben als Wortbestandteil zu betrachten und nicht nur die ASCII diejenigen in Nicht-ASCII - locales.Eine andere Alternative:
Dies ist eine Wortgrenze (eine, auf die keine Folge von Wortzeichen folgt, von denen sich eines wiederholt), gefolgt von 10 Wortzeichen.
Dinge, die man möglicherweise im Hinterkopf haben sollte:
Babylonish
zum Beispiel eine Übereinstimmung erzielt wird, da alle Zeichen unterschiedlich sind, obwohl es zweiB
s gibt, einen Kleinbuchstaben und einen Großbuchstaben (-i
zum Ändern verwenden).-w
,\w
und\b
, ist ein Wort , einen Buchstabe (ASCII diejenigen nur für GNUgrep
für jetzt , die[:alpha:]
Zeichenklasse in Ihrem Gebietsschema bei Verwendung von-P
und(*UCP)
), Dezimalstellen oder Unterstrich .c'est
(zwei Wörter gemäß der französischen Definition eines Wortes) oderit's
(ein Wort gemäß einigen englischen Definitionen eines Wortes) oderrendez-vous
(ein Wort gemäß der französischen Definition eines Wortes) nicht als ein Wort betrachtet werden.(*UCP)
wenn Unicode-Kombinationszeichen nicht als Wortbestandteile betrachtet werden, wirdtéléphone
($'t\u00e9le\u0301phone'
) als 10 Zeichen betrachtet, von denen eines kein Alpha ist.défavorisé
($'d\u00e9favorise\u0301'
) würde übereinstimmen, obwohl es zweié
Zeichen hat, da dies 10 verschiedene Alpha-Zeichen sind, gefolgt von einem kombinierten Akzent (kein Alpha, daher gibt es eine Wortgrenze zwischen deme
und seinem Akzent).quelle
\w
stimmt aber nicht überein-
.Okay ... hier ist der umständliche Weg für eine fünfstellige Zeichenfolge:
Weil Sie keinen Rückverweis in einer Zeichenklasse (zB setzen kann
[^\1|\2]
), müssen Sie ein verwenden negativen Vorgriff -(?!foo)
. Dies ist eine PCRE-Funktion, daher benötigen Sie den-P
Schalter.Das Muster für eine 10-stellige Zeichenfolge ist natürlich viel länger, aber es gibt eine kürzere Methode, bei der eine Variable verwendet wird, die mit ". *" Im Lookahead übereinstimmt:
Nachdem ich Stephane Chazelas 'aufschlussreiche Antwort gelesen hatte, stellte ich fest, dass es für diese Funktion ein ähnliches einfaches Muster gibt, das über greps
-v
Schalter verwendet werden kann:Da die Prüfung jeweils um ein Zeichen fortgesetzt wird, wird geprüft, ob auf ein bestimmtes Zeichen null oder mehr Zeichen (
.*
) folgen, und anschließend wird eine Übereinstimmung für die Rückreferenz gefunden.-v
invertiert und druckt nur Dinge, die diesem Muster nicht entsprechen. Dies macht die Rückverweise nützlicher, da sie nicht mit einer Zeichenklasse negiert werden können.wird arbeiten, um eine Zeichenfolge beliebiger Länge mit eindeutigen Zeichen zu identifizieren, wobei:
wird nicht, da es jedes Suffix mit eindeutigen Zeichen abgleichen wird (z. B.
abcabc
passt wegenabc
am Ende undaaaa
wegena
am Ende - daher jede Zeichenfolge). Dies ist eine Komplikation, die durch Lookarounds mit der Breite Null verursacht wird (sie verbrauchen nichts).quelle
(.)(?!.*\1)(.)(?!.*\2)(.)(?!.*\3)(.)(?!\4).
Wenn Sie das Ganze nicht in Regex erledigen müssen, würde ich es in zwei Schritten erledigen: Zuerst alle 10-Buchstaben-Wörter abgleichen und dann nach Eindeutigkeit filtern. Der kürzeste Weg, wie ich das machen kann, ist in Perl:
Beachten Sie die zusätzlichen
\W
Anker, um sicherzustellen, dass nur Wörter mit einer Länge von genau 10 Zeichen übereinstimmen.quelle
Andere haben vorgeschlagen, dass dies ohne verschiedene Erweiterungen bestimmter regulärer Expressionssysteme, die tatsächlich nicht regulär sind, nicht möglich ist. Da die gewünschte Sprache jedoch endlich ist, ist sie eindeutig regelmäßig. Für 3 Buchstaben aus einem 4-Buchstaben-Alphabet wäre es einfach:
Offensichtlich gerät dies mit mehr Buchstaben und größeren Buchstaben in Eile außer Kontrolle. :-)
quelle
Option
--perl-regexp
(short-P
) von GNUgrep
verwendet leistungsfähigere reguläre Ausdrücke, die Vorausschau-Muster enthalten. Das folgende Muster sucht nach jedem Buchstaben, den dieser Buchstabe im Rest des Wortes nicht enthält:Das Laufzeitverhalten ist jedoch ziemlich schlecht, da
\w*
es eine nahezu unendliche Länge haben kann. Es kann begrenzt werden\w{,8}
, aber das prüft auch über das Wortlimit von 10 Buchstaben. Daher überprüft das folgende Muster zuerst die korrekte Wortlänge:Als Testdatei habe ich eine große ≈ 500 MB-Datei verwendet:
Aktualisieren:
Ich konnte keine signifikante Änderung im Laufzeitverhalten für einen nicht gierigen Operator (
\w*?
) oder einen besitzergreifenden Operator ((...){10}+
) finden. Ein kleines bisschen schneller scheint die Alternative zu sein-w
:Ein Update von grep von Version 2.13 auf 2.18 war viel effektiver. Die Testdatei dauerte nur ca. 6 s.
quelle
\w{,8}?
) für eine Art von Eingabe hilfreich war (wenn auch nicht sehr bedeutend). Gute Verwendung\g{-1}
, um den GNU-Grep-Bug zu umgehen.\g{-1}
, weil dadurch das Muster von der Position unabhängiger wird. In dieser Form kann es als Teil eines größeren Musters verwendet werden.Eine Perl-Lösung:
aber es funktioniert nicht mit
oder
getestet mit perl v5.14.2 und v5.18.2
quelle