Странное поведение grep с ls и регулярными выражениями

Вопрос или проблема

Я учился использовать команды linux, когда заметил это странное необычное поведение команды “grep”. В каталоге /usr/bin, когда я выполняю:

me@me-desktop:/usr/bin$ ls -l | grep bashb*
-rwxr-xr-x 1 root root        6988 31 мар 2024 bashbug

что и ожидалось, но если я сделаю то же самое вне /usr/bin

me@me-desktop:~/Code/linux$ ls -l /usr/bin | grep bashb*
-rwxr-xr-x 1 root root     1446024 31 мар 2024 bash
-rwxr-xr-x 1 root root        6988 31 мар 2024 bashbug
-rwxr-xr-x 1 root root        4527 17 апр 2023 dh_bash-completion
lrwxrwxrwx 1 root root           4 20 авг 23:14 rbash -> bash

Как видите, теперь он необязателен игнорирует последнюю b в bashb.

Это происходит и в многих других случаях. Например, если вы выполняете apt list | grep lib*, то он также выводит те, которые содержат li.

Ответ или решение

Странное поведение команды grep с ls и регулярными выражениями

При использовании командной строки в Linux, особенно таких, как ls и grep, могут возникнуть неожиданные результаты, которые могут сбивать с толку. Рассмотрим случай, когда вы заметили странное поведение команды grep, проверяя имена файлов в директории /usr/bin.

Описание проблемы

Вы выполнили следующую команду в директории /usr/bin:

me@me-desktop:/usr/bin$ ls -l | grep bashb*

В результате вы получили:

-rwxr-xr-x 1 root root        6988 Mar 31  2024 bashbug

Это соответствует вашим ожиданиям, так как bashbug содержит bashb.

Однако, когда вы выполнили ту же команду в другой директории, как показано ниже:

me@me-desktop:~/Code/linux$ ls -l /usr/bin | grep bashb*

Вы получили больше результатов:

-rwxr-xr-x 1 root root     1446024 Mar 31  2024 bash
-rwxr-xr-x 1 root root        6988 Mar 31  2024 bashbug
-rwxr-xr-x 1 root root        4527 Apr 17  2023 dh_bash-completion
lrwxrwxrwx 1 root root           4 Aug 20 23:14 rbash -> bash

Причины странного поведения

Причина такого поведения заключается в том, как работает globbing (маскировка имен файлов) в оболочке Bash, а также в том, как grep обрабатывает регулярные выражения.

  1. Глоббинг в Bash:
    Когда вы пишете bashb*, оболочка интерпретирует * как подстановочный символ. Это значит, что Bash сначала пытается подставить все файлы и директории, соответствующие шаблону bashb*. В контексте первой команды (ls -l) в директории /usr/bin, подстановка ничего не возвращает, так как нет файлов, соответствующих шаблону перед grep. Таким образом, grep получает чистый шаблон bashb без дополнительных символов после него.

  2. Обработка регулярных выражений в grep:
    Когда вы выполняете grep bashb* в втором случае, grep получает список, где шаблон включает самые разные строки, и это оказывается не таким уж строгим. Pitfall заключается в том, что * в регулярных выражениях, как правило, интерпретируется как "ноль или более вхождений предыдущего символа". То есть bashb* может соответствовать bash, bashb, и даже строкам, которые содержат bash, а затем некоторый символ (или не содержат его). Поэтому результат содержит как bash, так и bashbug.

  3. Другие примеры:
    Подобное поведение наблюдается и в других ситуациях. Например:

    apt list | grep lib*

    Данная команда возвращает результаты не только с lib, но и с li, так как * работает аналогичным образом, расширяя шаблон.

Рекомендации

  1. Экранирование специального символа:
    Если вы хотите, чтобы grep обрабатывал именно то, что вы указали без глобального расширения, вы можете экранировать * с помощью обратного слэша:

    ls -l | grep 'bashb\*'

    Или использовать одинарные кавычки для определения строки:

    ls -l | grep 'bashb*'
  2. Использование регулярных выражений:
    Если вам нужно точное совпадение, используйте метасимвол ^ в начале и $ в конце:

    ls -l | grep '^bashb$'

    Это гарантирует, что grep будет искать точное совпадение с ‘bashb’, а не с любыми строками, которые могут его содержать.

Заключение

В процессе работы с Linux-командами важно понимать, как работает оболочка и инструменты с регулярными выражениями. Это знание поможет избежать путаницы и повысит эффективность работы с командной строкой. При возникновении сомнений в поведении команды всегда обращайтесь к документации и пробуйте различные варианты команд для достижения нужного результата.

Оцените материал
Добавить комментарий

Капча загружается...