Рассмотрим следующий входной файл:
1
2
3
4
Бег
{ grep -q 2; cat; } < infile
ничего не печатает. Я ожидаю, что это напечатает
3
4
Я могу получить ожидаемый результат, если я изменю его на
{ sed -n 2q; cat; } < infile
Почему первая команда не выводит ожидаемый результат?
Это доступный входной файл и в соответствии со стандартом в разделе ОПЦИИ :
-q
Quiet. Nothing shall be written to the standard output, regardless of
matching lines. Exit with zero status if an input line is selected.
и далее вниз, в разделе ИСПОЛЬЗОВАНИЕ ПРИЛОЖЕНИЯ (выделите мое):
-q
Вариант обеспечивает средство легко определить , существует ли или нет образец (или строка) в группе файлов. При поиске в нескольких файлах это обеспечивает улучшение производительности ( потому что он может выйти, как только найдет первое совпадение ) [...]
Теперь, в соответствии с тем же стандартом (во введении , под INPUT FILES )
Когда стандартная утилита считывает искомый входной файл и завершает работу без ошибки до того, как достигнет конца файла, утилита должна убедиться, что смещение файла в описании открытого файла правильно расположено сразу после последнего байта, обработанного утилитой [. ..]
tail -n +2 file
(sed -n 1q; cat) < file
...
Вторая команда эквивалентна первой, только если файл доступен для поиска.
Почему grep -q
потребляет весь файл?
Это gnu grep
если это имеет значение (хотя Кусалананда только что подтвердил, что то же самое происходит в OpenBSD)
grep
- это форк чего-то, называемого FreeGrep , если кому-то интересно.Ответы:
grep
останавливается рано, но буферизует входные данные, поэтому ваш тест слишком короткий (и да, я понимаю, что мой тест несовершенен, так как его нельзя найти):начинается в 6776 в моей системе. Это соответствует буферу 32 КБ, используемому по умолчанию в GNU grep:
выходы
Обратите внимание, что POSIX упоминает только улучшения производительности
Это не создает никаких ожиданий для улучшения производительности из-за частичного чтения одного файла.
источник
Это, очевидно, связано с буферизацией,
grep
которая ускоряет процесс. Есть инструменты, которые специально предназначены для чтения столько символов, сколько требуется, и не более. Одним из них являетсяexpect
:У меня нет системы, чтобы примерить это, но я верю,
expect
что съест все, пока не встретит ожидаемую строку (2
), а затем завершит работу, оставив остальную часть ввода дляcat
.источник
Вы путаете sed и grep.
Для команды sed
-2q
говорится , что нужно выйти из текущей итерации, если во второй строке-n
опция говорит, что она работает тихо, поэтому вы получите все строки после 2-й.По умолчанию команда grep выводит все совпадающие строки, но
-q
опция говорит, что ничего не выводится в стандартный вывод. таким образом, если вход содержит «2», он будет иметь выходное значение SUCCESS, иначе FAILURE. Что это такое, зависит от вашей операционной системы и оболочки. Таким образом, обычно вы определяете соответствие строки, проверяя выходное значение процесса grep. Это полезно в конвейере, где вы хотите знать, содержит ли ваш вход какое-либо значение в качестве теста. НапримерВ этом случае мы действительно не хотим видеть все совпадающие строки, мы просто заботимся, если хотя бы одна существует.
report_crash_via_email
Процесс / функция может затем гаснет и повторно открыть файл, или нет.Если вы хотите, чтобы ваш процесс grep ОСТАНОВИЛСЯ после того, как он обнаружил символ «2» - он не будет по умолчанию, он будет проверять каждую строку, проверяя, совпадает ли он, - вы должны сказать ему сделать это. Переключатель командной строки для этого есть
-m <value>
. Так что для вашего случаяgrep -q -m1 2
.источник
grep
но этот вопрос задает что-то более тонкое и эзотерическое. Похоже, вы прочитали вопрос слишком быстро, чтобы понять реальное запрашиваемое поведение. Кроме того , GNUgrep
делает остановки поиска при использовании-q
(как разрешено в цитате из спецификации POSIX): страница людей для GNU Grep гласит , что это «выход немедленно [S] с нулевым статусом если совпадение найдено» . FWIW, я отредактировал ваш вопрос, чтобы показать, как вы можете форматировать будущие сообщения. Добро пожаловать в стек обмена .grep
спрашивается, существует ли в файле «2», не больше и не меньше. Он не ведет себя какsed
и не использует записи до этого момента и оставляет остаток для дальнейшей обработки. Он читает до тех пор, пока не узнает, что есть «2» или что нет, закрывает файл и возвращает результат.grep
на самом деле только «использует весь файл» (игнорируя соображения буферизации), если строка поиска отсутствует в файле (что доказуемо только путем изучения всего файла). Все, что меньше, чтение файла останавливается , файл закрывается и возвращается SUCCESS.