В одном из моих лабораторных вопросов меня попросили перечислить все записи (и файлы, и папки) в текущем каталоге, имена которых содержат только заглавные буквы, используя команды piping и grep. Папки должны иметь косую черту. Первоначально мое решение выглядело так:
ls -p | grep -e "^[[:upper:]]*\/?$"
Я думал, что могу защитить знак «/» обратной косой чертой (как в echo \*
против echo *
). Тем не менее, это не работает, как задумано. Один из моих друзей предложил следующее решение:
ls -p | grep -e '^[[:upper:]]*/\? Я понятия не имею, почему используется обратный слеш. Что еще более странно, для меня, что это на самом деле дает правильный результат. Мне было интересно, если кто-то может объяснить, где ошибка в моем решении и почему вторая версия на самом деле работает.
Я понятия не имею, почему используется обратный слеш. Что еще более странно, для меня, что это на самом деле дает правильный результат. Мне было интересно, если кто-то может объяснить, где ошибка в моем решении и почему вторая версия на самом деле работает.
По умолчанию, grep
основные регулярные выражения (BRE) использования, в который ?
соответствует литеральному вопросительному знаку. Добавление обратной косой черты заставило его иметь Вашу желаемую интерпретацию как квантор, означающий "нуль или случаи предыдущего выражения" (т.е. дополнительно соответствующий запаздыванию /
).
От man grep
:
Basic vs Extended Regular Expressions In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \).
Вы могли достигнуть того же путем переключения на grep
в режим расширенного регулярного выражения (ERE) путем добавления -E
или --extended-regexp
флаг:
ls -p | grep -E -e '^[[:upper:]]*/?$'
Отметьте это /
является литеральным и в BRE и в ПРЕЖДЕ ЧЕМ - так не должен быть оставлен ни в одном случае.
Вы могли также рассмотреть использование -x
осуществлять соответствие целой строки без явного ^
и $
привязки.
Обратите внимание, что (хотя это прекрасно как осуществление), передавая по каналу ls
кому: grep
обычно не рекомендуемый способ выбрать файлы. В ударе Вы могли вместо этого рассмотреть использование расширенного globbing:
shopt -s extglob nullglob
ls -pd *([[:upper:]])