다음 형식으로 시간을 출력하는 프로그램이 있습니다.
2s576039936ns
다음 형식으로 변환해야 합니다.
2.576039936
쉘 스크립트에서 이 작업을 어떻게 수행할 수 있습니까?
고쳐 쓰다:이 ns
섹션은 9자리 숫자로 채워지지 않으므로 2s513ns
이와 같은 출력이 나올 수 있으므로 2.000000513
.
답변1
2s576039936ns
이 솔루션은 다음도 처리합니다 2s123ns
.
$ echo 2s576039936ns | tr '[:alpha:]' ' ' | awk -- '{ printf "%d.%09d",$1,$2 }'
2.576039936
$ echo 2s123ns | tr '[:alpha:]' ' ' | awk -- '{ printf "%d.%09d",$1,$2 }'
2.000000123
답변2
Bash의 이 기능을 사용할 수 있습니다(POSIX인지 확실하지 않음).
x=2s576039936ns
y=${x/s/.}
z=${y/ns/}
echo $z
또는 sed
:
echo 2s576039936ns | sed 's/s/./; s/ns//'
두 방법 모두 먼저 s를 점으로 바꾼 다음 ns를 삭제합니다.
완전히 다른 경우:
echo 2s576039936ns | awk -F '[ns]' '{print $1 "." $2}'
이것은 당신이 단지 변화를 원한다고 가정합니다체재숫자보다는.
답변3
그리고 perl
:
$ echo 10000s12576039936ns 1s1ns 0001s1000000ns 12s0ns |
perl -Mbignum -pe 's{(\d+)s(\d+)ns}{$1 + $2 / 1e9}ge'
10012.576039936 1.000000001 1.001 12
산술 연산에서 초 + 나노초 값으로 작업할 때 임의의 정밀도(여기에서 사용)가 종종 필요합니다. bignum
예를 들어 프로세서/C 컴파일러로 인해 정밀도를 나노초까지 유지하려는 경우 도구에서 일반적으로 사용되는 유형입니다. 산술 연산을 수행하는(쉘 없이...) 정밀도가 충분하지 않습니다.perl
struct timespec
clock_gettime()
double
awk
perl
bignum
그리고 zsh
:
string='10000s12576039936ns 1s1ns 0001s1000000ns 12s0ns'
set -o extendedglob
newstring=${string//(#b)(<->)s(<->)ns/\
$((match[1] + match[2] / 10**9))${${:-.${(l[9][0])match[2]}}%%(.|)0#}}
10012.576039936 1.000000001 1.001 12
그것도 제공할 것입니다 $newstring
(여기서는 두 숫자 모두에 대해 정수 산술을 사용하고 또한 이와 같은 부동소수점 zsh
에 대해서도 사용 double
합니다).
답변4
"텍스트 표현"만 변환하려는 것 같으므로 명령의 출력을 파이프할 수 있습니다 sed
. 다음 명령은 먼저 제거된 ns
후 다음 s
으로 대체됩니다 .
.
~$ echo "2s576039936ns" | sed -e 's/ns//' -e 's/s/./'
2.576039936
고쳐 쓰다
의견에서 나노초 부분은 정확히 9자리까지 0으로 채워지지 않는다는 점을 지적하셨습니다. 이 경우 출력이 올바르지 않게 됩니다. 이 문제를 해결하려면 다음 솔루션을 사용할 수 있습니다 awk
.
~$ echo "2s576039936ns" | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}'
s
이는 필드 구분 기호 로 또는를 사용하고 ns
(다중 문자 필드 구분 기호는 다중 문자 문자열이 아닌 정규 표현식으로 해석됨) .
구분 기호로 사용하여 필드 1과 필드 2를 인쇄합니다(후자는 이제 0에서 9까지 채워집니다). 소수점 자리).
따라서 스크립트에서 다음을 사용할 수 있습니다.
t=$( your_command | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}' )