1

Почему time ls | grep real вывод это

real    0m0.002s
user    0m0.000s
sys     0m0.002s

вместо просто

real    0m0.002s

Если я наберу

echo -e 'real\t0m0.002s\nuser\t0m0.000s\nsys\t0m0.002s\n' | grep real

Я получаю то, что ожидаю, т.е.

real    0m0.002s

Я обнаружил, что это работает

(time ls)  2>&1 > /dev/null | grep real

Что делает эта команда?

4 ответа4

4

Почему time ls | grep real работает не так, как ожидалось.

time это зарезервированное для bash слово, которое ведет себя иначе, чем /usr/bin/time .

Если слово с зарезервированным временем предшествует конвейеру, истекшее время, а также пользовательское и системное время, затраченное на его выполнение, сообщаются, когда конвейер завершается.

Исходный код bash(1): GNU Bourne-Again SHell - справочная страница по Linux

Кроме того, time выводит на стандартную ошибку, а не на стандартный вывод.

Используйте следующую команду:

(time ls) 2>&1 >/dev/null | grep real 

Заметки:

  • ( И ) группирует команды time и ls вместе (поэтому эти команды оцениваются первыми)
  • 2>&1 >/dev/null сначала перенаправляет stderr на стандартный вывод (который является каналом), а затем перенаправляет стандартный вывод на /dev/null .

    Так что stderr идет в трубу, а stdout никуда не идет.


Дальнейшее чтение

3

Да, это работает, но требует небольшого перенаправления ввода / вывода :)

$ exec 3>&1 4>&2
{ time sleep 1 1>&3 2>&4; } 2>&1 |
    grep 'real'    
exec 3>&- 4>&-

Выход :

real    0m1,003s

Прочтите bash FAQ # 32 и учебник по перенаправлению ввода / вывода


Более простой способ:

$ TIMEFORMAT=%R
$ time sleep 1
1,003
2

Два вопроса здесь.

Первое и самое важное, "время" отправляет свой вывод в stderr (стандартная ошибка), а не в stdout, так что он не будет захвачен обычными командами перенаправления, если вы не примете специальные меры.

Во-вторых, time - это не обычная программа, а специальная встроенная команда, интерпретируемая непосредственно оболочкой (для оболочек, таких как bash, csh, tcsh и т.д.). Таким образом, он работает нестандартным образом и время всей остальной части командной строки (если вы не используете очень необычную оболочку).

Итак, чтобы получить желаемый результат (используя bash), вам нужно использовать:

(time ls) 2>&1 | grep real

Это запустит "ls" в подоболочке и рассчитает время [ (time ls) ], отправит стандартную ошибку в standard out [2> & 1] , а затем отправит стандартную ошибку в "grep" [ | grep ].

Последняя часть, которую вы использовали ">?dev/null "выбрасывает нормальный вывод самой команды ls, в том случае, если в нее включено слово" real ".

1

Похоже, что time пишет напрямую в консоль, а не в stdout , что означает, что добавление time не влияет на вывод команды или конвейера.

Поэтому grep никогда не видит отчет о времени, который в любом случае генерируется после завершения grep , поскольку весь конвейер рассчитан по времени.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .