2012-04-28 9 views
6

Perl의 Time :: HiRes 모듈을 호출하여 경과 시간을 계산하는 스크립트가 있습니다. 다시 틱 통해 펄 인터프리터에쉘 스크립트 변수에 저장된 Perl 코드를 어떻게 실행할 수 있습니까?

use Time::HiRes qw(time); print time 

을하고 결과를 다시 가져옵니다 는 기본적으로 스크립트는 다음 한 줄을 전달하여 시간을 가져옵니다.

#/bin/sh 

START_TIME=`perl -e 'use Time::HiRes qw(time); print time'` 
END_TIME=`perl -e 'use Time::HiRes qw(time); print time'` 
ELAPSED_TIME=$(echo "($END_TIME - $START_TIME)" | bc) 
echo $ELAPSED_TIME 

나는 더 모듈 식 방법으로 재 작성하려고하지만 bash 쉘의 인용 규칙에 의해 난처한 해요.

#/bin/sh 
CALCULATE='bc' 
NOW="perl -e 'use Time::HiRes qw(time); print time'" 
START_TIME=`$NOW` 
[Some long running task ...] 
ELAPSED_TIME=$(echo "($NOW - $START_TIME)" | $CALCULATE) 
echo $ELAPSED_TIME 

Bash는 무엇인가 잘못 인용되지 않는다고 불평합니다. 왜 bash는 $ NOW에서 명령을 확장하고 실행되도록 백 tick에 전달하지 않습니까?

셸 스크립트 변수에 perl 코드를 포함시키는 데 여러 가지 방법을 시도했지만 올바르게 이해할 수없는 것 같습니다. .

누구나 쉘 스크립트에서 perl 코드를 올바르게 인용 할 수 있습니다. 함수를 사용하여

+0

@Mat 사람들이 쉽게 대답 할 수 있도록하기 위해 나는 훨씬 더 큰 스크립트의 발췌문을 보여 주었다. 나는 그것을 잘못 잘라내어 붙여 넣었다. 지적 해 주셔서 고마워요. 결정된. 그러나 문제는 아직도 인용하고있다. – GeneQ

+1

참고로, perl-one-liner를'perl -MTime :: HiRes = time -e 'print time''으로 작성할 수 있습니다. –

답변

7

이 작업을 수행 할 수있는 가장 간단한 방법이다, 나는 생각하지 :

#! /bin/bash 

now() { 
    perl -e 'use Time::HiRes qw(time); print time'; 
} 

calc=bc 
time1=$(now) 
time2=$(now) 
elapsed=$(echo $time2 - $time1 | $calc) 
echo $elapsed $time1 $time2 

은 본질적으로 필요 인용이.

+0

그게 전부입니다! 바보 나. 상자에 갇히는 것에 대해 이야기하십시오. 나는 Bash가 완전한 fledge 프로그래밍 언어라는 것을 때때로 잊는다. 감사. – GeneQ

3

여러분의 문제는 $NOW은 일부 펄 코드가있는 문자열 일뿐입니다. 당신은 역 따옴표 또는 $()로, 그것을 실행하는 bash는 말할 필요도

ELAPSED_TIME=$(echo "($($NOW) - $START_TIME)" | $CALCULATE) 

, bash는 기본적 연산을 할 수 없다 :

ELAPSED_TIME=$(($($NOW) - $START_TIME)) 

bc를 호출 할 필요가 있습니다.

마지막으로 perl을 시작하고 중지하는 데 많은 시간이 걸리므로 결과에 노이즈가 추가됩니다. perl을 한 번만 실행하고 perl 자체에서 장기 실행 작업을 실행하는 것이 좋습니다. 그런 다음뿐만 아니라 펄 자체 내에서 모든 계산을 할 거라고 :

#!/usr/bin/perl 

use Time::HiRes qw(time); 

my $start = time; 
system(@ARGV); 
my $end = time; 

print "Elapsed: ", ($end - $start), "\n" 

아니면 그냥 bash는이 time (또는 /usr/bin/time)이 단지 바로 모든 타이밍을 할 내장 사용할 수 있습니다.

+0

Perl 인터프리터 로딩 시간에 대한 좋은 지적이 있습니다. 그러나 그것은 내가 유지하고있는 오래된 코드이므로 너무 많이 변경하고 싶지는 않습니다. Perl로 전환하는 것은 리팩토링이 아닌 포팅이 될 것이고, 이는 너무 많은 작업입니다. 나는 그것을 순수 Perl로 쓰는 것을 선호한다. – GeneQ

+4

"bc를 호출 할 필요가 없습니다"- 내 bash (및'expr')는 십진수의 산술 연산을 수행하지 않습니다. – Mat

+0

@Mat, ah, yes, zsh, 거기서 조금 벗어났다. – bdonlan

1

$NOW이 따옴표 밖에 있으면 공백으로 분리됩니다.

$ perl -E'say [email protected]; say for @ARGV' $NOW 
7 
perl 
-e 
'use 
Time::HiRes 
qw(time); 
print 
time' 

이를 방지하기 위해 이중 따옴표로 변수를 둘러싸고 수 있습니다

$ perl -E'say [email protected]; say for @ARGV' "$NOW" 
1 
perl -e 'use Time::HiRes qw(time); print time' 

하지만 당신은 쉘 명령과 해당 문자열을 실행합니다. 이를 위해서는 eval을 사용하십시오.

$ eval "$NOW" 
1335602750.57325 

마지막으로, 할당, 우리는 역 따옴표 (또는 이에 상응하는 $(...))를 사용합니다.

$ START_TIME=$(eval "$NOW") 
$ echo $START_TIME 
1335602898.78472 

이전에 게시 된 기능은 분명히 분명하지만 더 이상 인용 할 필요가 없다고 말했습니까? 그런데


,

perl -e 'use Time::HiRes qw(time); print time' 

perl -MTime::HiRes=time -e'print time' 

과도 단축 할 수있다 (후미 라인이 완벽하게 정상적으로 때문에) 다음

perl -MTime::HiRes=time -E'say time' 

또는 정말로 골을 쓰고 싶다면 F :

아래
perl -MTime::HiRes=time -Esay+time 
+1

색깔 끝에 조금 추가했다. – ikegami

0

이 스크립트의 수정 된 버전입니다, 당신은 기본적으로 일부 응용 프로그램 (표준 오차) stderr에 대한 thiere 표준 출력을 가지고 있음을 이해할 필요가있다 그래서 당신이 보지 않을 때, 자신의 출력은 변수에 넣어 당신 단지

#/bin/sh 
CALCULATE='bc' 
echo 'starting' 
NOW=$(perl -e 'use Time::HiRes qw(time); print time' 2>&1) 
sleep 3 
echo 'ending' 
END_TIME=$(perl -e 'use Time::HiRes qw(time); print time' 2>&1) 
ELAPSED_TIME=$(echo "($NOW - $START_TIME)") 
echo $ELAPSED_TIME 
0

내가 사용이시 HiRes 시간의 이익은 펄이 상대적으로 무거운 외부 프로세스이며 별도로 두 번 호출한다는 사실에 의해 부정 생각 표준 출력 (표준 outputp)로 리디렉션해야합니다. 값에 소수 자릿수가 많이 필요하지 않은 경우. 당신은 bash에 내장 된 시간을 사용할 수있다.

task() { 
    [Some long running task ...] 
} 
TIMEFORMAT=%R 
elapse=$({ time task > task.out 2>&1; } 2>&1) 
echo $elapse 
관련 문제