2014-05-19 5 views
7

Ich habe eine Datei „dictionary.txt“ bezeichnet eine Liste aller möglichen Wörter enthalten, zB:Wie werden Zeilen gedruckt, die nur Zeichen aus einer Liste in BASH enthalten?

a 
aardvark 
act 
anvil 
ate 
... 

Wie ich diese suchen, nur Linien Druckbuchstaben aus einer begrenzten Liste, zum Beispiel, wenn die Liste enthält, die Buchstaben "c" enthält, "a" und "t", wird eine Suche diese Worte offenbaren:

a 
act 
cat 

Wenn die Buchstaben "e", "a" und "t" gesucht, nur diese Wörter werden von "dictionary.txt" gefunden:

a 
ate 
eat 
tea 

Die einzige Lösung, die ich es geschafft haben, ist dies:

  • eine Liste aller möglichen Buchstaben erstellen.
  • Löschen Sie die gesuchten Buchstaben aus dieser Liste und lassen Sie eine Liste mit Buchstaben, nach denen ich nicht suchen möchte.
  • Löschen Sie alle Zeilen aus dem Wörterbuch, das diese Buchstaben enthält, mit einer for-Schleife, die jeden dieser Buchstaben zyklisch abruft.
  • Drucken Sie die restlichen Wörter im Wörterbuch.

Diese Lösung ist sehr langsam. Außerdem muss ich diesen Code mit anderen Sprachen verwenden, die Tausende von möglichen Zeichen haben, so dass diese Suchmethode besonders langsam ist.

Wie kann ich nur die Zeilen aus "dictionary.txt" drucken, die nur die gesuchten Buchstaben enthalten, und sonst nichts?

+1

Ich sehe nicht, wie meine Lösung Fehler verursachen könnte; Sie waren vage in Ihrer Anwendungsfallbeschreibung: "Wenn die Liste die Buchstaben" c "," a "und" t "enthält, wird eine Suche diese Wörter aufdecken". Können Sie klären, wie Sie Informationen an Grep weitergeben? – amphetamachine

Antwort

18
grep '^[eat]*$' dictionary.txt 

Erläuterung:

^ = Marker Zeilenanfang bedeutet

$ = Marker Ende der Zeile Bedeutung

[abc] = Zeichenklasse ("entsprechen eines dieser Zeichen")

* = Multiplikator für Zeichenklasse (Null oder mehr Wiederholungen)

+0

Oh ja, und es ist auch gut zu sagen "[betrogen]", die wiederholte Buchstaben ignorieren und wie '[cheatd] ' – amphetamachine

+0

Wenn diese explizite Form führt zu' Argument Liste zu lang', ist es erwähnenswert, dass der Ausdruck auch Verwenden Sie Bereiche wie '[e-hk-oz]'. Dies kann hilfreich sein, wenn die fraglichen CJK-Zeichen benachbarte Codepunkte haben. –

+3

Dies könnte auch für leere Zeilen gelten. Besser verwenden Sie '\ +' oder '+' anstelle von '*'. – konsolebox

6

Versuchen Sie es awk mit:

awk '/^[eat]*$/ { print }' dictionary.txt 

Ich fand diese schneller zumindest eine Größenordnung sein als grep für mehr als etwa 7 Buchstaben. Ich weiß jedoch nicht, ob Sie mit Tausenden von Buchstaben auf dasselbe Problem stoßen werden, da ich nicht so viele getestet habe.

Sie können sogar nach mehreren Mustern gleichzeitig suchen (dies ist schneller als jedes Muster einzeln zu durchsuchen, da die Wörterbuchdatei nur einmal gelesen wird). Jedes Muster dient als if-Anweisung:

awk '/^[eat]*$/ { print "[eat]: " $0 } /^[cat]*$/ { print "[cat]: " $0 }' dictionary.txt 
+1

Ihr erster Vorschlag könnte auf 'awk'/^ [essen] * $/'dictionary.txt' reduziert werden - das '{print}' ist implizit. –

+0

@TomFenech Das ist praktisch! – savanto

8

Leider kann ich nicht kommentieren, sonst ich amphetamachine's answer hinzufügen würde.Wie auch immer, mit dem aktualisierten Zustand von Tausenden von Suchzeichen sollten Sie Folgendes tun:

grep -f patterns.txt dictionary.txt 

wo patterns.txt Ihr regexp ist:

/^[eat]\+$/ 

Im Folgenden finden Sie eine Beispielsitzung:

$ cat <<EOF> dictionary.txt 
> one 
> two 
> cat 
> eat 
> four 
> tea 
> five 
> cheat 
> EOF 
$ cat <<EOF> patterns.txt 
> ^[eat]\+$ 
> EOF 
$ grep -f patterns.txt dictionary.txt 
eat 
tea 
$ 

Auf diese Weise werden Sie nicht durch die Shell eingeschränkt (Argumentliste zu lang). Sie können aber auch mehrere Muster in der Datei angeben:

$ cat patterns.txt 
^[eat]\+$ 
^five$ 
$ grep -f patterns.txt dictionary.txt 
eat 
tea 
five 
$ 
5
sed -n '/a/'p words.txt 

verwendet für den Buchstaben, Sie finden müssen. Wenn Sie mehr als einen Buchstaben zusammen finden möchten, wiederholen Sie einfach den Befehl.

Grep sollte auch nicht für mehr als die einfachste/elementare Suche, IMHO verwendet werden. Obwohl ich normalerweise zögere, irgendwelche POSIX-Dienstprogramme als veraltet zu bezeichnen, versuche ich grep zu vermeiden. Seine Syntax ist äußerst inkonsistent.

Das Studium dieser Textdatei wird ebenfalls empfohlen. http://sed.sourceforge.net/sed1line.txt

1

Wenn Sie z.B. Umlaute im Muster und nicht die anderen Akzente haben wollen, setze die LC_ALL="C" vor der Ausführung des Grep.

Dies z.B. gibt Ihnen nur die deutschen Kandidatenwörter in einer möglichen dictionary.txt-Datei.

LC_ALL="C" grep '^[a-zA-ZäÄöÖüÜß]*$' dictionary.txt 
Verwandte Themen