Muster am Zeilenende mit grep erkennen

65

Wenn ich mache:

$ ls -R
.:
4Shared/  Cloud/

./4Shared:
UFAIZLV2R7.part3.rar

./Cloud:
UFAIZLV2R7.part2.rar.part
UFAIZLV2R7.part1.rar.part
UFAIZLV2R7.part4.rar.part

Wenn ich .rarnur die Dateien auflisten möchte und grep verwende , werden mir auch die .rar.partDateien angezeigt, was nicht mein Wunsch ist.
Ich löse dies mit findoder ls **/*.rarwie in diesem Thread beschrieben und sie funktionieren einwandfrei, aber ich würde gerne erfahren, ob es möglich ist, dies über zu tun grep.

Ich habe versucht (nachzudenken EOL):

ls -R | grep ".rar\n"

ohne ergebnisse.
Ich denke, dass das Problem darin liegt, herauszufinden, ob das Greifen am Ende der Zeile gefunden wird , aber ich bin nicht sicher.

Können Sie uns bitte hier weiterhelfen?

Sopalajo de Arrierez
quelle
Warum sollten Sie grepin diesem Fall verwenden? Warum nicht find?
Devnull
1
@devnull, in vielen Fällen kann es hilfreich sein, zu wissen, wie Muster erkannt werden, die sich nur am Ende einer Zeile befinden. Zum Beispiel: Portabilität, Verwendung in Routern mit eingebettetem, zu simpelem Linux, Verwendung mit UnxUtils für Windows (sein findBefehl widerspricht dem von Windows) und ... Lernen ;-). Die Frage
bezieht
1
Um ehrlich zu sein, sollten Sie verwenden, wenn Sie auf das Ende einer Zeile als Trennzeichen zählen ls -1R.
mikeserv
1
Und du brauchst nicht mal grep. Siehe meine Antwort.
mikeserv
@mikeserv, was könnte ohne den -1RSchalter passieren . Anscheinend sind die Ergebnisse gleich.
Sopalajo de Arrierez

Antworten:

89

Der $Anker stimmt mit dem Ende einer Zeile überein.

ls -R | grep '\.rar$'

Sie können dafür auch verwenden find:

find . -name '*.rar'
Jordanien
quelle
Ich habe das "." muss in grep entkommen werden. Wird es als Platzhalter behandelt?
Thebunnyrules
1
@thebunnyrules "." in Regex bedeutet eines von jedem Zeichen.
Jordanien
10

Zusätzlich zu Ihrer Frage beachten Sie bitte, dass .rarnicht nur ".rar", sondern jedes einzelne Zeichen (einschließlich .) vor dem ".rar" übereinstimmt rar. In diesem Fall wahrscheinlich kein Problem, sondern .muss in regulären Ausdrücken maskiert werden.

ls -R | grep "\.rar$"
Hauke ​​Laging
quelle
Meinten Sie das .ascist wie *ascMuster? So wird es zum Beispiel passen whereverasc.
Sopalajo de Arrierez
2
@SopalajodeArrierez Nein, es stimmt nicht mit jeder Zeichengruppe überein, sondern mit jedem einzelnen Zeichen, z xrar.
Hauke ​​Laging
5

Sie können auch anweisen grep, nach einer Zeichenfolge zu suchen, die an einer Wortgrenze beginnt. A .ist eine dieser Grenzen.

$ ls -R | grep '\brar$'

Beispiel

Angenommen, ich habe diese Beispieldaten.

$ ls -1
afile.rar
xrar
UFAIZLV2R7.part1.rar.part
UFAIZLV2R7.part2.rar.part

Dieser Befehl würde nur die Datei mit der .rarErweiterung finden.

$ ls -R | grep '\brar$'
afile.rar

Wie funktioniert das?

Das Metazeichen \bist ein Anker wie das Caret und das Dollarzeichen. Es stimmt mit einer Position überein, die als "Wortgrenze" bezeichnet wird. Diese Übereinstimmung hat die Länge Null.

Situationen, in denen dies nicht funktioniert

Wenn Sie Dateien mit Namen haben, werden blah-rardiese ebenfalls erkannt.

$ ls -R | grep '\brar$'
afile-rar
afile.rar

Dies liegt daran, dass andere Zeichen als alphanumerische Zeichen normalerweise als Begrenzungszeichen betrachtet werden und daher an diesem Ansatz vorbeigehen würden.

slm
quelle
Scheint auf den ersten Blick gleich zu sein, aber es ist in der Tat etwas anders. Danke, @slm. Ist es störend, wenn ich doppelte Anführungszeichen "anstelle einfacher Anführungszeichen verwende?
Sopalajo de Arrierez
1
@SopalajodeArrierez - Nö funktioniert so oder so. Hiermit werden alle Dateien gefunden, die ab w / benannt werden können .rar. Dies ist jedoch kein Problem bei der Verwendung von ls -R. Nur wenn du es zufällig benutzt hast ls -Ra.
SLM
Wäre einer von Ihnen daran interessiert, der Öffentlichkeit diesen kleinen Unterschied zu erklären?
Hauke ​​Laging
@HaukeLaging Der -PUmstieg auf grepin meinem Beispiel. Dies löst eine PCRE-Interpretation des Arguments aus.
slm
1
@SopalajodeArrierez - Wenn eine Datei ein Newline-Zeichen ( \n) enthält, das ein zulässiges Zeichen ist. Das ls -1Rzwingt die Dateien unabhängig in einer einzigen Spalte angezeigt werden.
SLM
0

Mach einfach :

ls -1R -I"?" -I"??" -I"???" -I"*[!.][!r][!a][!r]"

Das brauchst du gar nicht grep.

ANMERKUNG: Das oben Genannte funktioniert ... außer es wird immerhin noch afile-rar und ich verstehe nicht warum. Ich lasse es hier, aber ich bin nicht stolz darauf. Auf jeden Fall, wie andere gesagt haben:

find . '*.rar'
mikeserv
quelle
Dies hat keine Dateien namens xraroder blockiert afile-rar.
SLM
Ich bekomme immer noch die anderen Dateien in der Ausgabe.
SLM
@slm Welche anderen Dateien? Ich denke, es könnte sein, dass sie zu kurz sind. Das habe ich gerade selbst gemerkt. Das habe ich auch behoben.
mikeserv
Die Dateien afile-rarund xrarwerden weiterhin in die Ausgabe einbezogen. Auch bei deinen neuesten Mods gibt es keine Änderungen. Lästiges Problem nein? Es macht Spaß, es ohne die üblichen Methoden zu lösen. 8-)
slm
@slm Ja, deshalb komme ich her. Ich verstehe nicht, warum das -dashdurchkommt. Die xrarSache, die ich behandeln konnte, aber nicht die -dash.ich nicht verstehe-dash.
mikeserv
0

Verwenden Sie einfache Anführungszeichen, damit das $ als Zeilenende funktioniert. Wenn Sie auch eine Variable verwenden möchten, verwenden Sie die folgende Kombination aus doppelten und einfachen Anführungszeichen:

grep "$var"'$'

Mein vorheriger Beitrag wurde gelöscht, da er doppelt vorhanden ist. Lassen Sie mich erklären, wie das anders ist.

In den anderen Beiträgen wird entweder die vollständige Verwendung von doppelten Anführungszeichen ""oder die vollständige Verwendung von einfachen Anführungszeichen erwähnt ''. Sie haben beide ihre eigenen Grenzen. Das Folgende erklärt es.

Das Problem mit allen doppelten Anführungszeichen ist folgendes: grep "pattern$"gibt folgenden Fehler aus:Illegal variable name.

Die Verwendung aller einfachen Anführungszeichen funktioniert, aber wenn Sie eine variable Ersetzung wünschen, funktionieren alle einfachen Anführungszeichen nicht . Zum Beispiel:

Wenn ich eine Zeichenfolge habe A_BOOK, einschließlich anderer Zeichenfolgen in einer Datei DATEI.

$ cat FILE
A_BOOK
B_BOOK_NOT_LAST
C_BOOK

Wenn ich das BOOK auf eine Variable BK setze

set BK = BOOK

Wenn ich mit allen doppelten Anführungszeichen grep, erhalte ich den folgenden Fehler:: grep "${BK}$" FILE*1. $ für die Variablensubstitution, 2. für das Ende des Musters ( unzulässiger Variablenname ).

Wenn ich mit allen einfachen Anführungszeichen greife, findet die Variablensubstitution nicht statt. grep '${BK}$' FILEgibt nichts zurück

Wenn ich eine Kombination aus doppelten und einfachen Anführungszeichen verwende, erhalte ich das, was ich erwarte. Doppelte Anführungszeichen für die Variablensubstitution und einfache Anführungszeichen für das Musterende.

$ grep "${BK}"'$'  # << gives expected output
A_BOOK
C_BOOK
user274900
quelle
Sieht aus wie Sie csh verwenden. Die "foo$"Syntax funktioniert gut für sh und family.
Olorin
Ja, Olorin. Ich benutze tcsh. Vielen Dank für den Hinweis.
user274900
0

Wenn nach dem Befolgen der obigen Anweisungen nichts funktioniert, kann dies an Zeilenenden liegen. Um das Problem zu beheben, führen Sie Folgendes aus: dos2unix pr0n.txtund grepwiederholen Sie den Vorgang.

typelogisch
quelle