Wykrywanie wzoru na końcu linii za pomocą grep

64

Jeśli zrobię:

$ ls -R
.:
4Shared/  Cloud/

./4Shared:
UFAIZLV2R7.part3.rar

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

Jeśli chcę wylistować .rartylko pliki i użyję grep , pokaże mi także .rar.partpliki, czego nie chcę.
Rozwiązuję to za pomocą findlub ls **/*.rarjak powiedziano w tym wątku i działają one dobrze, ale chciałbym się dowiedzieć, czy można to zrobić za pośrednictwem grep.

Próbowałem (zastanawiając się EOL):

ls -R | grep ".rar\n"

bez rezultatów.
Myślę, że problem polega na odkryciu, czy greping znajduje się na końcu linii , ale nie jestem pewien.

Jakaś pomoc tutaj?

Sopalajo de Arrierez
źródło
Dlaczego miałbyś chcieć użyć grepw tym przypadku? Dlaczego nie find?
devnull
1
@devnull, wiedza na temat wykrywania wzorców, które znajdują się tylko na końcu linii, może być przydatna w wielu przypadkach. Na przykład: przenośność, użycie w routerach z osadzonym zbyt uproszczonym Linuksem, użycie z UnxUtils dla Windows (jego findpolecenie jest w konflikcie z Windowsem) i ... nauka ;-). Pytanie nie dotyczy „
Listowania plików w katalogu
1
szczerze mówiąc, jeśli liczysz na koniec linii jako separatora, powinieneś użyć ls -1R.
mikeserv
1
I nawet nie potrzebujesz grep. Zobacz moją odpowiedź.
mikeserv
@mikeserv, co mogłoby się stać bez -1Rprzełącznika. Najwyraźniej wyniki są takie same.
Sopalajo de Arrierez

Odpowiedzi:

88

$Kotwica dopasowuje koniec linii.

ls -R | grep '\.rar$'

Możesz również użyć finddo tego:

find . -name '*.rar'
Jordan
źródło
Nie zdawałem sobie sprawy z „.” trzeba uciec w grep. Czy to jest traktowane jak dzika karta?
thebunnyrules
1
@thebunnyrules "." w wyrażeniu regularnym oznacza jedną z dowolnych postaci.
Jordan
10

Oprócz pytania pamiętaj, że .rarnie tylko pasuje do „.rar”, ale także do każdego znaku (w tym .) przed rar. W tym przypadku prawdopodobnie nie jest to problem, ale .należy go unikać w wyrażeniach regularnych.

ls -R | grep "\.rar$"
Hauke ​​Laging
źródło
Czy oznacza to, że .ascjest jak *ascwzorzec? Więc będzie pasować na przykład whereverasc.
Sopalajo de Arrierez
2
@SopalajodeArrierez Nie, nie pasuje do każdej grupy znaków, ale do każdej pojedynczej postaci, np xrar.
Hauke ​​Laging
5

Możesz również poinstruować, grepaby szukać łańcucha od granicy słowa. A .jest jedną z takich granic.

$ ls -R | grep '\brar$'

Przykład

Powiedz, że mam te przykładowe dane.

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

To polecenie odnalazłoby tylko plik z .rarrozszerzeniem.

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

Jak to działa

Metaznak \bjest kotwicą podobną do karetki i znaku dolara. Pasuje do pozycji zwanej „granicą słowa”. To dopasowanie jest zerowej długości.

Sytuacje, w których to nie zadziała

Jeśli masz pliki o nazwach, blah-rarzostaną one również wykryte.

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

Wynika to z faktu, że znaki inne niż alfanumeryczne są zwykle uważane za znaki graniczne, a więc wymykałyby się temu podejściu.

slm
źródło
Na pierwszy rzut oka wydaje się, że jest tak samo, ale w rzeczywistości jest nieco inny. Dzięki, @slm. Czy to przeszkadza, jeśli używam podwójnych cudzysłowów "zamiast prostych cudzysłowów?
Sopalajo de Arrierez
1
@SopalajodeArrierez - nope nie działa w żaden sposób. Znajdziesz tu wszystkie pliki, które można nazwać od w / .rar. Ale to nie będzie problem z użyciem ls -R. Tylko jeśli zdarzyło Ci się użyć ls -Ra.
slm
Czy ktoś z was byłby zainteresowany wyjaśnieniem tej drobnej różnicy opinii publicznej?
Hauke ​​Laging
@HaukeLaging -PPrzełącz się na grepw moim przykładzie. To powoduje interpretację argumentu przez PCRE.
slm
1
@SopalajodeArrierez - jeśli plik zawiera znak nowej linii ( \n), który jest znakiem prawnym. ls -1RZmusi pliki mają być wyświetlane w jednej kolumnie niezależnie.
slm
0

Po prostu zrób :

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

W ogóle nie potrzebujesz grep.

UWAGA: Powyższe działa ... z wyjątkiem tego, że wciąż się pojawia afile-rar i nie rozumiem dlaczego. Zostawię to tutaj, ale nie jestem z tego dumny. W każdym razie, jak powiedzieli inni:

find . '*.rar'
mikeserv
źródło
Nie blokowało to plików o nazwach xrarlub afile-rar.
slm
Nadal otrzymuję inne pliki na wyjściu.
slm
@slm Jakie inne pliki? Myślę, że może to być spowodowane tym, że są za krótkie. Właśnie to zauważyłem. Też to naprawiłem.
mikeserv
Pliki afile-rari xrarnadal są uwzględniane w danych wyjściowych. Brak zmian w najnowszych modach. Paskudny problem nie? Zabawnie jest próbować go rozwiązać bez zwykłych metod 8-)
slm
@slm Tak, dlatego tu przybyłem. Nie rozumiem, dlaczego tak się dzieje -dash. xrarRzeczą, jaką może obsłużyć, ale nie -dash.mogę nie zrozumieć-dash.
mikeserv
0

Użyj pojedynczych cudzysłowów, aby $ działał jako koniec linii. Jeśli chcesz również grepować przy pomocy jakiejś zmiennej, użyj kombinacji podwójnych i pojedynczych cudzysłowów jak poniżej:

grep "$var"'$'

Mój poprzedni post został usunięty, mówiąc, że jest zduplikowany. Pozwól mi wyjaśnić, jak to jest inaczej.

Pozostałe posty wspominają albo o pełnym wykorzystaniu podwójnych cudzysłowów "", albo o pełnym wykorzystaniu pojedynczych cudzysłowów ''. Oba mają swoje własne ograniczenia. Wyjaśnia to.

Problem ze wszystkimi podwójnymi cudzysłowami jest następujący: grep "pattern$"daje następujący błąd:Illegal variable name.

I użycie wszystkich pojedynczych cudzysłowów działa, ale jeśli chcesz podstawić zmienne, wszystkie pojedyncze cudzysłowy nie będą działać. Na przykład:

Jeśli mam ciąg A_BOOK, w tym inne ciągi w pliku PLIK.

$ cat FILE
A_BOOK
B_BOOK_NOT_LAST
C_BOOK

Jeśli ustawię BOOK na zmienną BK

set BK = BOOK

Jeśli grep ze wszystkimi podwójnymi cudzysłowami, otrzymuję następujący błąd:: grep "${BK}$" FILE*1st $ dla podstawienia zmiennej, 2nd dla końca wzorca ( niedozwolona nazwa zmiennej ).

Jeśli grep ze wszystkimi pojedynczymi cudzysłowami, podstawienie zmiennej nie nastąpi. grep '${BK}$' FILEnic nie zwraca

Jeśli użyję kombinacji podwójnych i pojedynczych cudzysłowów, otrzymam to, czego oczekuję. Podwójne cudzysłowy dla podstawienia zmiennej i pojedyncze cudzysłowy dla końca wzorca.

$ grep "${BK}"'$'  # << gives expected output
A_BOOK
C_BOOK
użytkownik274900
źródło
Wygląda na to, że używasz csh. "foo$"Składnia działa dobrze na sh i rodziny.
Olorin
Tak, Olorin. Używam tcsh. Dzięki za wskazanie tego.
user274900
0

Jeśli po wykonaniu powyższego i nic nie działa, może to być spowodowane zakończeniami linii. Aby to naprawić, wykonaj: dos2unix pr0n.txti wykonaj grepponownie.

typelogiczny
źródło