Предположим, что каталог содержит 100 файлов, начинающихся с буквы «а».
Если я сделаю grep <some string> a*
из терминала, как оболочка справится с этим?
Будет ли он расширять регулярное выражение, получать список всех файлов, начинающихся с a и grep для каждого из них последовательно? Или есть какой-то другой способ?
Предположим, что у меня есть массив вышеуказанных имен файлов, которые начинаются с «а». Будет ли это занимать больше / меньше времени, если я напишу цикл for и сам выполню итерацию в сценарии оболочки или в программе ac?
glob
не регулярное выражение. Большая разница.Ответы:
Во-первых, придирка: строка, как
a*
в обычном синтаксисе оболочки - это глоб, который работает не так, как регулярные выражения.В высокоуровневом обзоре интерпретатор оболочки (т.е. bash) расширяет строку
a*
до списка каждого имени файла, соответствующего шаблонуa*
. Затем они становятся частью параметров командной строки для одного экземпляраgrep
(для программистов все расширенные слова идут как отдельные строки вargv
аргументmain
). Эта единственнаяgrep
команда затем анализирует аргументы любым способом, который она выберет, и она должнаgrep
интерпретировать эти аргументы как имена файлов, опции, аргументы опций, регулярные выражения и т. Д. И предпринимать соответствующие действия. Все происходит последовательно (AFAIK безgrep
реализации использует несколько потоков).Если вы реализуете цикл в сценарии оболочки, чтобы сделать то же самое, он почти гарантированно будет медленнее, чем описанный выше процесс, по следующим причинам. Если вы создадите новый процесс grep для каждого файла, он наверняка будет медленнее из-за ненужного умножения затрат на создание процесса. Если вы сами создали список аргументов в сценарии оболочки и использовали один экземпляр
grep
, все, что вы делаете в оболочке, все равно будет медленнее, потому что команды оболочки должны интерпретироваться (посредством bash), что добавляет дополнительный слой кода, и вы просто заново реализуйте то, что bash уже делал быстрее внутри в скомпилированном коде.Что касается написания этого самостоятельно на C, вы, вероятно, можете легко получить производительность, сопоставимую с процессом, описанным в первом абзаце, но вряд ли вам удастся добиться достаточного прироста производительности по сравнению с текущими реализациями grep / bash, чтобы оправдать время не тратя времени на оптимизацию производительности для конкретной машины или жертвуя переносимостью. Может быть, вы могли бы попытаться придумать произвольно распараллеливаемую версию
grep
, но даже это может не помочь, так как вы скорее связаны с вводом / выводом, чем с процессором. Расширение glob и grep уже «достаточно быстры» для большинства «обычных» целей.источник
zcat
иzgrep
; не нужно распаковывать их один за другимДа, он расширится до списка файлов и передаст полученный список в
grep
программу. По крайней мере, такman bash
говорится в подразделе « Расширение пути» .Существует другой способ использования расширения в простых случаях, как вы упомянули: написать
grep <some_string> a
и перед нажатием*
нажать ESC. Это расширит список подходящих файлов прямо в командной строке, так что вы можете проверить, что список в порядке, прежде чем нажимать Enter.Что касается второй части вашего вопроса, это зависит. Если вы хотите написать цикл for, который запускает grep для каждого из файлов по очереди, то это определенно будет медленнее, поскольку программа grep будет запускаться не один раз, а один раз для каждого файла. Однако, что это важно иметь в виду, что существует определенный предел на расширенной длины аргументов командной строки , которые можно использовать, хотя это , как правило , довольно высока. Чтобы увидеть это, вы можете попробовать
grep adasdsadf /usr/*/*/* >/dev/null
.источник
ESC+*
это не то же самое, что позволить bash раскрыть *, потому чтоESC+*
будет вставлять точечные файлы (имена, начинающиеся с a.
), тогда как расширение*
зависит отdotglob
shopt
настроек. Последовательность клавиш для раскрытия и вставки глобусов используетсяC-x *
по умолчанию и соответствует команде readlineglob-expand-word
.a*
расширения, но, безусловно, важно в более широком контексте.zsh
примечание: простое нажатие клавиши табуляции на расширяемых параметрах (шаблонах глобусов, раскладывании скобок, подстановках команд и т. д.) раскроет их.C-x
ярлык, и он не расширяет список файлов в моей системе (используя bash).C-x *
только глобусы, которые только делают имена файлов, но наEsc *
самом деле делают намного больше, поскольку это такinsert-completions
, как и во всех возможных дополнениях. Это означает, что использованиеEsc *
в пустой командной строке вставит имя каждого исполняемого файла$PATH
, например, в ваш .