쉘: 배쉬.
목표: printf를 사용하여 타임스탬프 처리에 적합한 고정된 시점 이후의 시간 t(밀리초)를 가져옵니다.
조건: 솔루션은 전체 줄 텍스트 테스트를 통과해야 합니다.
또한 솔루션은 원자성(예, 맞습니다!..)이어야 하고, 가벼워야 하며, 양자화 및 반올림 문제를 최소한으로 유지해야 합니다.
t=$[$(date +%s%N)/1000000]
<--- 내 솔루션, 이 경우 고정점은 1970년 1월 1일입니다. 하지만 더블 데이트 콜 때문에 근본적으로 안 좋은 상황이 됐다.
printf "t=%d\n" $[$(date +%s%N)/1000000]
<--- 바로 printf를 사용하는 것입니다.
t=$(date +%s)$[10#$(date +%N)/1000000]
<---끔찍한 예입니다. 앞의 0을 제거한 다음 다시 채워야 하는 것처럼 보입니다.
printf "t=%d%03d\n" $(date +%s) $[10#$(date +%N)/1000000]
<--- 바로 printf를 사용하는 것입니다.
더 나은 (현인한) 조언이 있습니까?
편집(추가):
t=$(date +%s%N)
그럼 printf "%s\n" ${t::13}
<--- 내 생각엔 한 줄도 아닌 것 같은데.
답변1
bash5+부터 시작하는 간단한 솔루션이 있습니다.
$ printf "%.3f\n" $EPOCHREALTIME
1566917328.786
이 점이 필요하지 않은 경우:
printf "%s\n" "$((${EPOCHREALTIME/.}/1000))"
한 줄의 텍스트, 원자성(내부 bash 변수에 대한 한 번의 호출), 경량이며 양자화 또는 반올림 문제가 없는 에포크 이후의 시간을 밀리초 단위로 제공합니다.
답변2
@Isaac이 지적했듯이 date
GNU 또는 ast-open 등을 지원하는 구현을 사용하면 이를 사용하여 정밀도를 제한할 수 있지만,%N
%s%3N
ksh93
date
할 수 있는ast-open 의 내장 버전으로 만들어졌지만 date
이 date
명령은 내장되어 있지 않습니다. 시작하는 데 수백 또는 수천 마이크로초가 걸리며 날짜와 그 뒤를 인쇄하는 데는 훨씬 더 걸립니다.
bash
형식의 하위 집합은 실제로 복사되지만 일부는 ksh93
printf '%(...)T'
복사되지 않습니다 %N
.
ksh93
여기서는 또는 와 같은 고급 쉘을 사용해야 할 것 같습니다 zsh
.
이러한 쉘은 $SECONDS
변수가 쉘이 시작된 이후의 시간을 기록하도록 할 수 있습니다(그리고 임의의 값으로 재설정할 수도 있음) 부동 소수점:
$ typeset -F SECONDS=0; date +%s%3N; echo $SECONDS
1506318780647
0.0017870000
date
여기서 GNU를 실행하는 데 1787마이크로초가 걸렸습니다.
$((SECONDS*1000))
다음을 사용하여 밀리초를 ksh93
얻을 수 있습니다 .
부동 소수점 숫자로 된 에포크 시간의 경우 다음이 zsh
있습니다 $EPOCHREALTIME
.
$ zmodload zsh/datetime
$ echo $EPOCHREALTIME
1506318947.2758708000
작동 ksh93
합니다 "$(printf '%(%s.%N)T' now)"
( ksh93
명령 대체는 프로세스를 분기하지 않으며 내장 파이프를 사용하지 않으므로 다른 Bourne과 같은 쉘만큼 비싸지 않습니다).
다음을 사용하여 변수를 정의 할 수도 있습니다 $EPOCHREALTIME
.
$ EPOCHREALTIME.get() { .sh.value=$(printf "%(%s.%6N)T");
$ echo "$EPOCHREALTIME"
1506333341.962697
set -o xtrace
자동 타임스탬프의 경우 및 a를 사용하여 $PS4
현재 시간을 인쇄 할 수도 있습니다 . 존재하다 zsh
:
$ zsh -c 'PS4="+%D{%s.%.}> "; set -x; sleep 1; date +%s.%N'
+1506332128.753> sleep 1
+1506332129.754> date +%s.%N
1506332129.755322928
ksh93에서:
$ ksh -c 'PS4="+\$(printf "%(%s.%3N)T")> "; set -x; sleep 1; date +%s.%N'
+1506332247.844> sleep 1
+1506332248.851> date +%s.%N
1506332248.853111699
moreutils
사용 사례에 따라 타임스탬프를 사용할 수도 있습니다 ts
.
$ (date +%s.%6N; date +%s.%6N) | ts %.s
1506319395.000080 1506319394.970619
1506319395.000141 1506319394.971972
( ts
파이프를 통해 출력에서 한 줄을 읽는 데 걸리는 시간을 제공합니다).date
또는 출력 행 사이의 시간에 대해 다음을 수행합니다.
$ (date +%s.%6N; date +%s.%6N) | ts -i %.s
0.000011 1506319496.806554
0.000071 1506319496.807907
특정 명령(파이프라인)을 실행하는 데 걸린 시간을 확인하려면 키워드를 사용하여 time
형식을 다음과 같이 조정할 수도 있습니다.$TIMEFORMAT
bash
$ TIMEFORMAT=%E; time date
Mon 25 Sep 09:51:41 BST 2017
0.002
이러한 시간 형식 지침은 원래 csh에서 나왔습니다(반대로 bash
GNU zsh
는 time
매우 작은 하위 집합만 지원함). (t)csh에서는 $time
특수 변수를 설정하여 각 명령의 시간을 측정할 수 있습니다.
$ csh -xc 'set time = (0 %E); sleep 1; sleep 2'
set time = ( 0 %E )
sleep 1
0:01.00
sleep 2
0:02.00
(여기서 첫 번째 숫자( 0
여기)는 해당 수초 이상 걸리는 명령의 시간을 측정해야 함을 나타내고, 두 번째 숫자는 형식을 지정합니다.
답변3
- 우선 이
date
도구는 bash의 일부가 아니며 외부 도구입니다. - Bash 자체는 외부 명령 없이는 이 작업을 수행할 수 없습니다.
- 외부 명령을 사용하여 이 작업을 수행하면 한 줄 기준에 실패합니다.
따라서 이 작업을 수행할 수 없습니다.
다만, 2줄을 허용하거나, 댓글에 적힌 대로 이에 대한 함수를 작성하면 가능합니다.
확장하다:비록 여러분이 작성한 bash 라인 중 가장 쉬운 라인은 아닐지라도 최신 bash(>4.2)에서는 한 줄 명령으로도 이 작업을 수행할 수 있습니다. 다른 답변을 확인하세요.
답변4
너무 길어요.
$ date +'%s%3N'
1506298414529
세게 때리다
Bash 4.2부터 엄격한 bash 솔루션(외부 실행 파일 없음)을 사용할 수 있습니다.
$ printf '%(%s)T\n' "-1"
1506298414
$ printf '%(%Y%m%d-%H:%M:%S)T\n' "-1"
20170924-20:13:34
하지만 아직 밀리초나 나노초는 허용되지 않습니다.
날짜
밀리초 또는 나노초를 얻으려면 다음과 같이 GNU Date를 사용해야 합니다.
$ printf '%s\n' "$(date +'%Y%m%d-%H:%M:%S.%N')"
20170924-20:13:34.326113922
또는
$ printf '%s\n' "$(date +'%s.%N')"
1506298414.529678016
소수 초의 3자리 제한은 %.3f
printf 형식을 사용하여 생성할 수 있습니다.
$ printf '%.3f\n' "$(date +'%s.%N')"
1506298414.529
또는 더 나은 방법은 날짜 나노초 형식에 허용되는 자릿수를 줄이는 함수를 사용하는 것입니다.
$ printf '%s\n' "$(date +'%s.%3N')"
1506298414.529
그런 다음 포인트를 삭제할 수 있습니다.
$ printf '%s\n' "$(date +'%s%3N')"
1506298414529
물론, 이 경우 더 간단한 솔루션(printf가 없고 정확히 요청된 내용이 아님)이 더 적절해 보입니다.
$ date +'%s%3N'
1506298414529