Обнаружение шаблона в конце строки с помощью 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'
jordanm
источник
Я не понял "." нужно экранировать в 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
источник
На первый взгляд кажется одинаковым, но на самом деле он немного другой. Спасибо, @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'
mikeserv
источник
Это не блокировало файлы с именем 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
user274900
источник
Похоже, вы используете csh. "foo$"Синтаксис работает отлично на ш и семьи.
Олорин
Да, Олорин. Я использую tcsh. Спасибо за указание на это.
user274900
0

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

typelogic
источник