일련의 입력 변수에 대한 프로그램 실행 시간을 측정하고 싶습니다(저는 zsh를 사용하고 있습니다).
for i in {1..3} ; do time sleep $i ; done
출력은 다음과 같습니다
sleep $i 0,00s user 0,00s system 0% cpu 1,003 total
sleep $i 0,00s user 0,00s system 0% cpu 2,003 total
sleep $i 0,00s user 0,00s system 0% cpu 3,002 total
하지만 그랬으면 좋겠어
sleep 1 0,00s user 0,00s system 0% cpu 1,003 total
sleep 2 0,00s user 0,00s system 0% cpu 2,003 total
sleep 3 0,00s user 0,00s system 0% cpu 3,002 total
time
모든 변수를 해당 값으로 대체하여 실제 명령을 인쇄하려면 어떻게 해야 합니까 ?
서브셸에서 프로그램을 실행해 보았지만 예상대로 출력이 변경되지 않습니다.
for i in {1..3} ; do time (sleep $i) ; done
i
내 프로그램은 stdout 및 stderr에 대한 자체 출력을 생성하므로 다음과 같이 단순히 모든 인수(그들뿐만 아니라) 앞에 추가하는 방법을 찾지 못했습니다 .
for i in {1..3} ; do echo -n "i=$i --> " ; time sleep $i ; done
답변1
time
이는 키워드가 복합 명령에 적용될 수 있기 때문에 발생합니다 . (보다 정확하게는 파이프에서 작동합니다.) 다음과 같이 작성할 수 있습니다.
time (i=$(($(/bin/echo 1) + 1)); sleep $i)
zsh가 명령(계산 포함)을 구문 분석하는 데 걸리는 시간은 $i
타이밍의 일부입니다.
time
한 가지 해결책은 외부 명령을 사용하는 것입니다 . 외부 명령에서 작동하므로 쉘 확장은 타이밍의 일부가 아닙니다. GNU 시간 사용(명령은 기본적으로 인쇄되지 않음):
% for i in {1..3} ; do =time -f '%C %Us user %Ss system %P cpu %e total' sleep $i ; done
sleep 1 0.00s user 0.00s system 0% cpu 1.00 total
sleep 2 0.00s user 0.00s system 0% cpu 2.00 total
sleep 3 0.00s user 0.00s system 0% cpu 3.00 total
또 다른 해결책은 명령을 직접 인쇄하는 것입니다. 아래 코드는 명령 출력(있는 경우) 앞에 명령 텍스트를 인쇄합니다.
% for i in {1..3} ; do echo -n "sleep $i"; (TIMEFMT=${TIMEFMT#%J}; time sleep $i); done
sleep 1 0.00s user 0.00s system 0% cpu 1.004 total
sleep 2 0.00s user 0.00s system 0% cpu 2.004 total
sleep 3 0.00s user 0.00s system 0% cpu 3.004 total
또 다른 해결 방법은 명령 추적을 활성화하는 것입니다.
% for i in {1..3} ; do (TIMEFMT=${TIMEFMT#%J}; set -x; time sleep $i); done
+zsh:14> sleep 1
0.00s user 0.00s system 0% cpu 1.004 total
+zsh:14> sleep 2
0.00s user 0.00s system 0% cpu 2.004 total
+zsh:14> sleep 3
0.00s user 0.00s system 0% cpu 3.005 total
또 다른 해결책은 필요한 텍스트를 시간 형식에 삽입하는 것입니다.
% for i in {1..3} ; do (TIMEFMT="${${:-sleep $i}//\%/%%}${TIMEFMT#%J}"; time sleep $i); done
sleep 1 0.00s user 0.00s system 0% cpu 1.004 total
sleep 2 0.00s user 0.00s system 0% cpu 2.004 total
sleep 3 0.00s user 0.00s system 0% cpu 3.004 total
또 다른 해결책은 가능한 가장 간단한 쉘 명령을 구성하는 것입니다 eval
. 이것이 관련되어 있으므로 eval
명령에 쉘 특수 문자가 포함될 수 있는지 주의하십시오.
% for i in {1..3} ; do eval "time sleep $i"; done
sleep 1 0.00s user 0.00s system 0% cpu 1.002 total
sleep 2 0.00s user 0.00s system 0% cpu 2.005 total
sleep 3 0.00s user 0.00s system 0% cpu 3.004 total
답변2
다음을 수행할 수 있습니다.
$ for i in {1..3} ; do eval "time sleep $i:q"; done
sleep 1 0.00s user 0.00s system 0% cpu 1.004 total
sleep 2 0.00s user 0.00s system 0% cpu 2.003 total
sleep 3 0.00s user 0.00s system 0% cpu 3.002 total
( :q
이 경우 숫자만 포함된 경우에는 불필요하지만, 일반적인 경우 $i
어떤 명령에 리터럴 인수로 무언가를 전달하려는 경우에 필요합니다.)$i
%J
언제든지 원하는 텍스트로 바꿀 수도 있습니다 (작업 이름 1로 확장됨) $TIMEFMT
.
for i in {1..3}; do
TIMEFMT="sleep $i: %U user %S system %P cpu %*E total"
time sleep $i
done
( %
이 텍스트에 포함하려면 이스케이프 처리해야 한다는 점을 기억하세요 %%
.)
사실, 그것은 직위의 실제 이름이 아닙니다. 예를 들어, time sleep 1 | sleep 2
전체 파이프라인이 작업 인 경우 time
파이프라인의 각 섹션에 대해 하나씩 두 줄이 제공됩니다.