쉘 스크립트에서 시간 범위의 텍스트 표현 변환

쉘 스크립트에서 시간 범위의 텍스트 표현 변환

다음 형식으로 시간을 출력하는 프로그램이 있습니다.

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 컴파일러로 인해 정밀도를 나노초까지 유지하려는 경우 도구에서 일반적으로 사용되는 유형입니다. 산술 연산을 수행하는(쉘 없이...) 정밀도가 충분하지 않습니다.perlstruct timespecclock_gettime()doubleawkperlbignum

그리고 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}' )

관련 정보