너무 길어요.

너무 길어요.

쉘: 배쉬.

목표: 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이 지적했듯이 dateGNU 또는 ast-open 등을 지원하는 구현을 사용하면 이를 사용하여 정밀도를 제한할 수 있지만,%N%s%3Nksh93date 할 수 있는ast-open 의 내장 버전으로 만들어졌지만 datedate명령은 내장되어 있지 않습니다. 시작하는 데 수백 또는 수천 마이크로초가 걸리며 날짜와 그 뒤를 인쇄하는 데는 훨씬 더 걸립니다.

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형식을 다음과 같이 조정할 수도 있습니다.$TIMEFORMATbash

$ TIMEFORMAT=%E; time date
Mon 25 Sep 09:51:41 BST 2017
0.002

이러한 시간 형식 지침은 원래 csh에서 나왔습니다(반대로 bashGNU zshtime매우 작은 하위 집합만 지원함). (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

  1. 우선 이 date도구는 bash의 일부가 아니며 외부 도구입니다.
  2. Bash 자체는 외부 명령 없이는 이 작업을 수행할 수 없습니다.
  3. 외부 명령을 사용하여 이 작업을 수행하면 한 줄 기준에 실패합니다.

따라서 이 작업을 수행할 수 없습니다.

다만, 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자리 제한은 %.3fprintf 형식을 사용하여 생성할 수 있습니다.

$ 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

관련 정보