Обнаружение шаблона в конце строки с помощью grep


65

Если я сделаю:

$ ls -R
.:
4Shared/  Cloud/

./4Shared:
UFAIZLV2R7.part3.rar

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

Если я хочу перечислить .rarтолько файлы, и я использую grep , он также покажет мне .rar.partфайлы, чего я не желаю.
Я решаю это с помощью findили, ls **/*.rarкак сказано в этой теме, и они отлично работают, но я хотел бы узнать, если это возможно сделать через grep.

Я пытался (думая о EOL):

ls -R | grep ".rar\n"

без результатов.
Я думаю, что проблема заключается в обнаружении, если в конце строки обнаружен greping , но я не уверен.

Любая помощь здесь, пожалуйста?


Почему вы хотите использовать grepв этом случае? Почему нет find?
devnull

1
@devnull, знание того, как определять шаблоны, которые находятся только в конце строки, может быть полезно во многих случаях. Например: переносимость, использование в маршрутизаторах со встроенным слишком упрощенным Linux, использование с UnxUtils для Windows (его findкоманда конфликтует с Windows) и ... learning ;-). Вопрос не в «Списке файлов в директории» (это просто пользовательский пример), а в «Понимании использования команды grep»
Сопалахо де Арриерес

1
честно говоря, если вы рассчитываете на конец строки, чтобы быть вашим разделителем, то вы должны использовать ls -1R.
mikeserv

1
И тебе даже не нужно grep. Смотри мой ответ.
mikeserv

@mikeserv, что может случиться без -1Rвыключателя. Видимо результаты одинаковы.
Сопалахо де Арриерес

Ответы:


89

$Якорь соответствует концу строки.

ls -R | grep '\.rar$'

Вы также можете использовать findдля этого:

find . -name '*.rar'

Я не понял "." нужно экранировать в grep. Это рассматривается как джокер?
thebunnyrules

1
@thebunnyrules "." в регулярном выражении означает один из любых символов.
Иордания

10

В дополнение к вашему вопросу, обратите внимание, что .rarне только соответствует «.rar», но соответствует каждому отдельному символу (включая .) перед rar. В этом случае, вероятно, не проблема, но .должны быть экранированы в регулярных выражениях.

ls -R | grep "\.rar$"

Вы имели в виду, что .ascэто как *ascшаблон? Так будет соответствовать, например whereverasc,.
Сопалахо де Арриерес

2
@SopalajodeArrierez Нет, он не соответствует каждой группе символов, но каждому отдельному символу, например xrar.
Хауке Лагинг

5

Вы также можете поручить grepискать строку, начинающуюся с границы слова. А .является одной из таких границ.

$ ls -R | grep '\brar$'

пример

Скажем, у меня есть этот пример данных.

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

Эта команда найдет только файл с .rarрасширением.

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

Как это работает?

Метасимвол \b- это якорь, такой как каретка и знак доллара. Он соответствует позиции, которая называется «граница слова». Это совпадение нулевой длины.

Ситуации, когда это не сработает

Если у вас есть файлы с именами, blah-rarони также будут обнаружены.

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

Это связано с тем, что символы, отличные от буквенно-цифровых символов, обычно считаются граничными символами, и поэтому этот подход ускользнет.


На первый взгляд кажется одинаковым, но на самом деле он немного другой. Спасибо, @slm. Тебе мешает, если я использую двойные кавычки "вместо простых кавычек?
Сопалахо де Арриерес

1
@SopalajodeArrierez - Нет, работает в любом случае. Это найдет любые файлы, которые могут быть названы начиная с / .rar. Но это не будет проблемой с использованием ls -R. Только если вам случалось использовать ls -Ra.
СЛМ

Был бы один из вас заинтересован в объяснении этой небольшой разницы общественности?
Хауке Лагинг

@HaukeLaging -PПереключение на grepв моем примере. Это вызывает PCRE интерпретацию аргумента.
SLM

1
@SopalajodeArrierez - если файл содержит символ новой строки ( \n), который является допустимым символом. В ls -1Rлюбом случае файлы будут отображаться в одном столбце.
SLM

0

Просто сделать :

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

Вам не нужно grepвообще.

ПРИМЕЧАНИЕ: вышесказанное работает ... за исключением того, что оно все еще получается по крайней мере, afile-rar и я не понимаю, почему. Я оставлю это здесь, но я не горжусь этим. В любом случае, как говорили другие:

find . '*.rar'

Это не блокировало файлы с именем xrarили afile-rar.
SLM

Я все еще получаю другие файлы в выводе.
SLM

@slm Какие еще файлы? Я думаю, это может быть потому, что они слишком короткие. Я просто заметил это сам. Я тоже это исправил.
mikeserv

Файлы afile-rarи xrarдо сих пор включены в вывод. Без изменений с вашими последними модами тоже. Надоедливых проблем нет? Это весело, пытаясь решить эту проблему без обычных методов 8-)
slm

@Slm Да, именно поэтому я прихожу сюда. Я не понимаю, почему -dashпроходит. То, с xrarчем я мог справиться, но не то, что -dash.я не понимаю,-dash.
mikeserv

0

Используйте одинарные кавычки, чтобы $ работал как конец строки. Если вы хотите использовать grep с некоторой переменной, используйте комбинацию двойных и одинарных кавычек, как показано ниже:

grep "$var"'$'

Мой предыдущий пост был удален, говоря, что он дубликат. Позвольте мне объяснить, как это отличается.

Другие посты упоминают либо полное использование двойных кавычек "", либо полное использование одинарных кавычек ''. У них обоих есть свои ограничения. Следующее объясняет это.

Проблема со всеми двойными кавычками следующая: grep "pattern$"выдает следующую ошибку:Illegal variable name.

И использование всех одинарных кавычек работает, но если вы хотите подстановку переменных, все одинарные кавычки не будут работать. Например:

Если у меня есть строка A_BOOK, включая другие строки в файле FILE.

$ cat FILE
A_BOOK
B_BOOK_NOT_LAST
C_BOOK

Если я установил BOOK для переменной BK

set BK = BOOK

Если я выполняю grep со всеми двойными кавычками, я получаю следующую ошибку:: grep "${BK}$" FILE*1st $ для подстановки переменной, 2nd для конца шаблона ( недопустимое имя переменной ).

Если я буду использовать все одинарные кавычки, подстановка переменных не произойдет. grep '${BK}$' FILEничего не возвращает

Если я использую комбинацию двойных и одинарных кавычек, я получаю то, что ожидаю. Двойные кавычки для подстановки переменных и одинарные кавычки для конца шаблона.

$ grep "${BK}"'$'  # << gives expected output
A_BOOK
C_BOOK

Похоже, вы используете csh. "foo$"Синтаксис работает отлично на ш и семьи.
Олорин

Да, Олорин. Я использую tcsh. Спасибо за указание на это.
user274900

0

Если после выполнения вышеизложенного ничего не работает, это может быть связано с окончанием строки. Чтобы исправить, сделайте: dos2unix pr0n.txtи сделайте свое grepснова.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.