2010-10-13 39 views
15

Tôi đang vật lộn để phân tích đầu ra của lệnh thời gian trong bash - và thậm chí để ngăn chặn nó in ra đầu ra của nó khi tôi gọi nó. Đây là mã thử nghiệm của tôi:Đấu tranh để phân tích cú pháp (bash) lệnh thời gian

#!/bin/bash 
TIME=`time ls -lh > /dev/null` 
echo "Testing..." 
echo $TIME 

này hiện in ra:

{blank-line} 
real 0m0.064s 
user 0m0.002s 
sys  0m0.005s 
Testing 
{blank-line} 

Vì vậy, nó có vẻ như giá trị giao cho $TIME là dòng trống vào lúc bắt đầu của thời gian in ra. Tôi cần lấy giá trị giây của dòng sys - nghĩa là "0,005". Tôi đảm bảo rằng tôi sẽ chỉ bao giờ có giây, vì vậy tôi không cần bất cứ điều gì trước khi "m" - tuy nhiên, phần giây có thể ở dạng xx.xxx nếu nó đi> = 10 giây. Tôi hiện không có ý tưởng làm thế nào để ngăn chặn đầu ra 'thời gian', nắm bắt tất cả thay vì dòng trống, cũng không phân tích nó để có được các giá trị tôi cần.

Bất kỳ trợ giúp sẽ được nhiều đánh giá cao ...

Trả lời

16

Nếu bạn sử dụng Bash BUILTIN time, bạn có thể kiểm soát sản lượng của nó bằng cách thiết lập TIMEFORMAT biến:

TIMEFORMAT=%R 

và bạn sẽ không phải làm bất kỳ phân tích vì đó sẽ gây ra time để chỉ ra số lượng của giây.

và sử dụng này:

echo "Testing..." 
TIME=$({ time ls -lh > /dev/null; } 2>&1) 
echo $TIME 

hoặc một trong những kỹ thuật khác từ BashFAQ/032.

1

Các time lệnh đầu ra các thông tin thời gian để stderr, mà bạn không được chụp hoặc chuyển hướng. Vì vậy, tại thời điểm của bài tập, thông tin đó được in ra bảng điều khiển của bạn, trong khi biến số $TIME lấy STDOUT của lệnh - mà bạn đã chuyển hướng đến /dev/null, vì vậy nó sẽ trống.

Có lẽ bạn nên cố chụp STDERR của lệnh?

+0

Ah, tôi đã không nhận ra rằng thời gian đầu ra cho 'STDERR'. Làm cách nào để tôi ghi lại biến đó vào biến '$ TIME'? – Stephen

7

Đầu tiên và trước hết, dữ liệu bạn đang cố chụp sẽ được ghi vào lỗi chuẩn. Nhưng bắt đầu ra đó khá phức tạp trong trường hợp này.

time vừa là tệp thực thi (trong /usr/bin) cũng như lệnh trình bao tích hợp trong bash và các trình bao khác. Khi bạn thực hiện time mà không chỉ định /usr/bin/time, bạn đang thực hiện lệnh được cài sẵn trong bash. Điều này làm cho nó khó khăn để làm những việc với đầu ra, kể từ khi bash không đối xử với nó như một chương trình bình thường; nó là một hàm dựng sẵn đặc biệt được viết bởi bash.

Biết điều đó và xem trang người đàn ông cho time(1), tôi có thể thấy dữ liệu bạn đang cố gắng chụp từ time được xuất ra thành tiêu chuẩn. Vì vậy, cách giải quyết của tôi cho điều này là để trực tiếp thực hiện /usr/bin/time như sau:

TIME=`/usr/bin/time ls -lh 2>&1 >/dev/null` 

bản này dòng sai số chuẩn tiêu chuẩn ra, và sau đó chuyển hướng những gì bình thường đi vào tiêu chuẩn ra /dev/null. Tuy nhiên, lỗi chuẩn sẽ vẫn đi tiêu chuẩn vì nó đã được sao chép trước khi chuyển hướng. Đảo ngược thứ tự của những thứ này sẽ không hoạt động. (Vâng, đây là khó hiểu.)

Thật không may, /usr/bin/time là một chút ít chính xác về sản lượng của nó:

0.00 real   0.00 user   0.00 sys 

Ngoài ra, bạn có thể sử dụng 2 sub-vỏ, như sau:

TIME=$((time ls -lh >/dev/null) 2>&1) 

Điều này sẽ viết lại những gì được ghi vào lỗi tiêu chuẩn trên vỏ con thứ hai trong vòng đầu tiên, cho phép bạn nắm bắt đầu ra. Xem http://www.tldp.org/LDP/abs/html/subshells.html để biết thêm về các hệ vỏ phụ.

+0

Hoặc chỉ sử dụng một trình bao dưới dạng 'TIME =" $ ({time ls -lh>/dev/null;} 2> & 1) ' –

0

Tôi muốn đăng bài này làm nhận xét nhưng sẽ quá dài. Tôi muốn trình bày một cách hơi khác để có được dữ liệu.

Bạn có thể sử dụng hai vỏ con để có được đầu ra của thời gian dưới dạng luồng sử dụng /bin/sh thay vì /usr/bin/time để có được thời gian thực hiện. Tôi tưởng tượng bạn có thể thay thế time tại đây bằng /usr/bin/time.

$ ((time ./print_test.sh > deleteme) 2>&1) > deletemetime 

$ cat deleteme 
test 

$ cat deletemetime 
./print_test.sh > deleteme 0.00s user 0.00s system 86% cpu 0.003 total 

$ ((time ./print_test.sh > deleteme) 2>&1) | sed 's/system/kernel/' 
./print_test.sh > deleteme 0.00s user 0.00s kernel 86% cpu 0.003 total 

Cũng lưu ý rằng dường như có sự khác biệt về cách sản xuất. Đôi khi nó là ở định dạng đó và đôi khi nó là ở định dạng này:

real 0m0.420s 
user 0m0.385s 
sys  0m0.040s 

Không chắc vào thời điểm này những gì xác định một cách này hay cách khác.

Tất nhiên, bạn có thể sử dụng ví dụ:

TIMEFORMAT='%3R' 

để sửa định dạng.

2

Mặc dù giải pháp di chuột xung quanh cùng một logic, nhưng tôi vẫn không thể tìm thấy sau đây được liệt kê, vì vậy một phiên bản của giải pháp:

TIME=$(time (ls -lh >/dev/null) 2>&1) 
Các vấn đề liên quan