Cygwin 2.9.0. Команды cat / tac не работают с большими файлами при подключении к grep -q -m1

Я вижу какое-то странное поведение при использовании Cygwin x64 2.9.0 в Windows 10 Pro x64.Я пытаюсь запустить следующую команду:

tac <file> | grep -q -m1 -F "literal string"

Вышеупомянутая команда успешно обрабатывает все мелкие файлы, которые я ей добавляю (small означает <= 15kB). Это также считается успешным, если последнее вхождение буквальной строки находится рядом с началом файла (например, буквальная строка появляется в верхней части файла и больше нигде). Наконец, это также удается, когда ни один из флагов { -q , -m1 } не передается команде grep .

Однако, когда файл составляет около 680 КБ, и буквальная строка появляется ближе к концу файла, затем команда tac выводит «tac: ошибка записи» в STDERR. Несмотря на эту ошибку, команда, похоже, была успешной, распечатав соответствующую строку для вывода (когда флаг -q опущен) и получив соответствующее возвращаемое значение из grep .

Дальнейшее тестирование показало, что эта же ошибка возникает при использовании cat , за исключением того, что буквальная строка должна появляться рядом с началом файла для генерации ошибки, а сгенерированная ошибка - «cat: ошибка записи: на устройстве не осталось свободного места ».

Обратите внимание, что это происходит только в том случае, если хотя бы один из параметров { -m1 , -q } передан в grep совпадение находится рядом с первой обработанной строкой файла (для cat оно находится рядом с началом, для tac - ближе к концу), а файл большой.

Я выполнил команду df , и она сообщает, что на диске Cygwin доступно 14 МБ, а на самом диске свободно 60 ГБ. Я знаю, что могу просто перенаправить STDERR на устройство NUL, но это похоже на хакерский обходной путь. Кто-нибудь знает, как это исправить?

НАЧАТЬ РЕДАКТИРОВАНИЕ

Я нашел еще один отчет о той же ошибке от мая 2017 года, но решения не было представлено. OP другого сообщения действительно указывает, что он думает, что это ограничение размера буфера канала (возможно, в Windows, возможно, в Cygwin).

2
задан 21 January 2019 в 03:33
1 ответ

Я обнаружил несколько обходных путей. Просто измените команду:

tac <file> | grep -q -m1 -F "literal string"

на одну из:

bash -c "tac <file> | grep -q -m1 -F 'literal string'"
stdbuf -o L tac <file> | grep -q -m1 -F "literal string"

Я думаю, что первая работает, потому что она использует конвейер Linux, а вторая, потому что заставляет вывод команды tac буферизоваться по строке. Обе эти формы позволяют устранить ошибку.

Поскольку это работает, я предполагаю, что проблема в том, что grep прекращает обработку входного буфера после обнаружения первого совпадения, но tac продолжает обработку ввода. Когда буфер заполнен (вероятно, 64 КБ), буферные блоки и tac завершаются с указанной ошибкой. Однако, поскольку tac успешно обработал нужную мне строку до сбоя, все работает как задумано.

Выбор времени для этих параметров указывает на то, что вызов bash является более быстрым вариантом. Вероятно, это связано с тем, что при использовании конвейера Linux tac может вернуться сразу же, как только grep найдет первое совпадение.

0
ответ дан 3 December 2019 в 13:50

Теги

Похожие вопросы