Как сохранить подстроку вывода функции time в скрипте bash - PullRequest
7 голосов
/ 16 декабря 2010

Итак, встроенная функция времени для bash должна выводить в этом формате

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

Я хочу сэкономить время пользователя в миллисекундах, например, 001, как это сделать?

Ответы [ 3 ]

10 голосов
/ 16 декабря 2010

Чистый способ - использовать переменную оболочки TIMEFORMAT, чтобы печатать только пользовательскую информацию.(man bash для более подробной информации.)

Затем, конечно, вам нужно захватить вывод из него.Это невозможно сделать из конвейера, так как это делается внутри оболочки, но вы можете запустить его в подоболочке, и в результате вы получите стандартную ошибку.Но тогда вы должны каким-то образом перенаправить вывод команды в другое место.Здесь я просто отказываюсь от этого, но существует множество других возможностей, в зависимости от того, что именно вам нужно сделать.Тогда вам нужно загнать d.ddd в dddd.Просто удалите период.

(TIMEFORMAT="%U"; time ls > /dev/null) |& tr -d .

Если хотите, вы можете добавить | sed s/^0*//, чтобы удалить ведущие нули.

% R даст в реальном времени системное время% S,Вы можете изменить точность, например, с помощью% 6U, чтобы получить микросекунды, хотя большинство систем не будут иметь такую ​​точность.

man bash для получения справки о перенаправлениях.man tr и man sed для получения справки о том, как их использовать.

10 голосов
/ 16 декабря 2010

Встроенный Bash time немного сложен для захвата, потому что он имеет специальную обработку, так что он может возвращать время обработки для всего конвейера, такого как time ls -l | sort | uniq, а не только время обработки только для команды ls -l в моемпример.

Лучший способ захватить просто вывод времени - это следующая техника перенаправления:

exec 3>&1 4>&2
foo=$( { time some_command 1>&3 2>&4; } 2>&1 ) # change some_command
exec 3>&- 4>&-

В этот момент, если вы наберете echo "$foo", вы увидитечто-то порядка

real    0m0.013s
user    0m0.004s
sys     0m0.007s

Теперь, чтобы получить только часть 004, у вас есть довольно много вариантов: sed, awk или direct bash, чтобы назвать топ-3. Моим личным фаворитом будет awkи это выглядело бы примерно так:

foo=$({ time some_command 1>&3 2>&4;} 2>&1 | awk -F'[s.]' '/user/{print $3}')

Теперь, если бы вы были echo "$foo", вы бы увидели просто 004 как пожелаете

1 голос
/ 16 декабря 2010

Используя встроенную глобализацию строк в bash, вы можете сделать что-то вроде этого:

output="real 0m0.002s
user 0m0.001s
sys  0m0.000s"

#get everything to the right of first "*user "
user=${output#*user }
#get everything to the left of the first "s*"
user=${user%%s*}
#get everythig to let left of "m*"
min=${user%%m*}
#get everything to the right of "*m" and left of ".*"
sec=${user#*m}
sec=${sec%%.*}
#get everything to the right of "*."
usec=${user#*.}


time=$[$usec + $sec * 1000 + $min * 60000]

Запуск результатов bash -x

+ output='real 0m0.002s
user 0m0.001s
sys  0m0.000s'
+ user='0m0.001s
sys  0m0.000s'
+ user=0m0.001
+ min=0
+ sec=0.001
+ sec=0
+ usec=001
+ time=1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...