Как работает grep?
Я пытаюсь понять, как работает grep
.
Когда я говорю grep "hello" *.*
, grep
получает 2 аргумента — (1) строка для поиска, т.е. "Привет" и (2) путь *.*
? Или оболочка преобразует *.*
в нечто, что grep
может понять?
Где я могу получить исходный код grep
? Я наткнулся на эту ссылку GNU grep
. Один из файлов README отличается от unix grep
. Как это так?
Я хочу посмотреть источник версии FreeBSD grep
, а также версию Linux (если они разные).
Ответы
Ответ 1
В оболочке выполняется глобус (преобразование формы *
в имена файлов). Вы можете увидеть это, если у вас есть простая программа на C:
#include <stdio.h>
int main(int argc, char **argv) {
for(int i=1; i<argc; i++) {
printf("%s\n", argv[i]);
}
return 0;
}
И затем запустите его следующим образом:
./print_args *
Вы увидите, что он печатает, что соответствует, а не *
буквально. Если вы вызываете его так:
./print_args '*'
Вы увидите, что он получает буквальный *
.
Ответ 2
Сила grep
- магия теории автоматов. GREP является аббревиатурой для Global Regular Expression Print. И он работает, создавая автомат (очень простая "виртуальная машина": не Turing Complete); он затем "выполняет" автомат против входного потока.
Автомат - это граф или сеть узлов или состояний. Переход между состояниями определяется входным символом под контролем. Специальные автоматы, такие как +
и *
работают, имея переходы, которые возвращаются к себе. Классы символов, такие как [a-z]
, представлены вентилятором: один старт node с ветвями для каждого символа на "спицы"; и обычно спицы имеют специальный "переход эпсилон" в одно конечное состояние, поэтому его можно связать со следующим автоматом, который будет создан из регулярного выражения (строки поиска). Эпсилонные переходы позволяют изменять состояние, не перемещаясь вперед в поисках строки.
Изменить: Похоже, я не очень внимательно прочитал вопрос.
Когда вы вводите командную строку, она сначала обрабатывается оболочкой. Оболочка выполняет подстановки псевдонимов и имя файла. После замены псевдонимов (они похожи на макросы) оболочка прерывает командную строку в список аргументов (с разделителями по пробелам). Этот список аргументов передается функции main()
исполняемой команды программы как целочисленный счетчик (часто называемый argc) и указатель на NULL-конец ((void *)0
) массив с nul-terminated ('\0'
) char массивы.
Индивидуальные команды используют свои аргументы, как бы они ни желали. Но большинство программ Unix печатает дружественное справочное сообщение, если задано аргумент -h
(так как он начинается с знака минус, он называется опцией). Программное обеспечение GNU также примет вариант "long-form" --help
.
Поскольку существует множество различий между различными версиями программ Unix, самым надежным способом обнаружить точный синтаксис, который требуется программе, - это спросить саму программу. Если это не говорит вам, что вам нужно (или слишком загадочно понимать), вы должны проверить локальную страницу man (man grep
). А для программного обеспечения gnu часто можно получить еще больше информации от info grep
.
Ответ 3
Оболочка расширяет '*.*
' в список имен файлов и передает расширенный список имен файлов в программу, такую как grep
. Сама программа grep
не расширяет имена файлов.
Итак, ответ на ваш вопрос: grep
не получает 2 аргумента; оболочка преобразует '*.*
' во что-то grep
может понять.
GNU grep
отличается от Unix grep
поддержкой дополнительных параметров, таких как -w
и -B
и -A
.
Мне кажется, что FreeBSD использует версию GNU grep
:
Ответ 4
Как grep видит, что аргумент подстановки зависит от вашей оболочки. (Стандартная) У оболочки Bourne есть переключатель (-f), чтобы отключить имя файла globbing (см. справочные страницы).
Вы можете активировать этот переключатель в script с помощью
set -f