bash를 사용하여 부분 밀리초의 합계를 계산하는 방법은 무엇입니까?

bash를 사용하여 부분 밀리초의 합계를 계산하는 방법은 무엇입니까?

예제 00:03:03.333, 00:01:01.111, 00:02:02.222의 합을 변수에 넣는 방법

EPOCH='jan 1 1970'
offset=$EPOCH

lsdvd -c VIDEO_TS | grep "Length:" | grep "Chapter:" | awk '{print($4)}' | while read -r len
do
  len=${len:0:12}
  offset="$(date -u -d "$EPOCH $len" +%T.%3N) + $(date -u -d "$offset" +%T.%3N)"
  echo "need sum" $offset "then" ffmpeg -ss $offset ... -t $len ...
done

답변1

bcsh는 정수 연산만 수행할 수 있으므로 다른 것 (또는 awk나 Perl과 같이 정수가 아닌 연산을 수행할 수 있는 언어)을 사용해야 합니다 .

를 사용하려면 bc먼저 %H:%M:%S.%3N 형식을 초(소수 부분 포함)로 변환한 다음 로 파이프해야 합니다 bc.

예를 들어:

#!/bin/bash

epoch='1970-01-01'

len1='00:01:01.111'
len2='00:02:02.222'

# convert to seconds
len1_s=$(date -u -d "$epoch $len1" '+%s.%3N')
len2_s=$(date -u -d "$epoch $len2" '+%s.%3N')

# add the seconds
sum_s=$( echo "$len1_s + $len2_s" | bc )

echo $len1_s + $len2_s = $sum_s

# convert back to H:M:S.N
sum=$(date -u -d "@$sum_s" '+%T.%3N')

echo $len1 + $len2 = $sum

산출:

$ ./sum.sh 
61.111 + 122.222 = 183.333
00:01:01.111 + 00:02:02.222 = 00:03:03.333

구현은 잠시 동안 여러분에게 맡길 것입니다... 하지만 여기에는 lsdvd몇 초 안에 장 길이를 제공하는 몇 가지 유용한 출력 옵션이 있다는 점에 유의하겠습니다(따라서 변환할 필요가 없습니다). 아마도 가장 유용한 것은 장 길이를 처리 xmlstarlet하거나 추출하는 데 사용할 수 있는 XML 출력 옵션일 것입니다.xml2

예를 들어 여기의 XML 출력을 lsdvd라인 기반 형식(awk 또는 기타 수단을 사용한 처리에 적합)으로 변환하려면 다음을 사용하십시오 xml2.

이 동영상은 11개 챕터로 구성된 약 48분 분량의 동영상으로, 대부분 길이가 약 5분(300초)입니다.

$ lsdvd -c -Ox '/path/to/some/dvd.iso'  | xml2
/lsdvd/device=/path/to/some/dvd.iso
/lsdvd/title=TITLE
/lsdvd/vmg_id=DVDVIDEO-VMG
/lsdvd/provider_id=PROVIDER
/lsdvd/track/ix=1
/lsdvd/track/length=2874.667
/lsdvd/track/vts_id=DVDVIDEO-VTS
/lsdvd/track/chapter/ix=1
/lsdvd/track/chapter/length=299.934
/lsdvd/track/chapter/startcell=1
/lsdvd/track/chapter
/lsdvd/track/chapter/ix=2
/lsdvd/track/chapter/length=299.500
/lsdvd/track/chapter/startcell=2
/lsdvd/track/chapter
/lsdvd/track/chapter/ix=3
/lsdvd/track/chapter/length=300.000
/lsdvd/track/chapter/startcell=3
[...]
/lsdvd/track/chapter/ix=11
/lsdvd/track/chapter/length=176.734
/lsdvd/track/chapter/startcell=11
/lsdvd/longest_track=1

이것은많은사람이 읽을 수 있는 기본 출력보다 스크립트에서 처리하기가 더 쉽습니다 lsdvd. 예를 들어, 장 길이를 초 단위로 원하는 경우:

$ lsdvd -c -Ox /path/to/some/dvd.iso' | xml2 | \
     awk -F'[/=]' '$5 == "length" { print $6 }'
299.934
299.500
300.000
299.500
300.000
299.500
299.500
300.000
299.500
0.500
176.734

또한 awk를 사용하면 grep이 필요하지 않다는 점을 지적하고 싶습니다. 따라서 사람이 읽을 수 있는 출력을 사용하려면 후행 쉼표를 제거하는 것과 grep | grep | awk함께 다음과 같이 줄일 수 있습니다.len=${len:0:12}

lsdvd -c VIDEO_TS | awk -F' +|,' '/Chapter:/ && /Length:/ { print $5 }' | \
  while read len

필드 구분 기호는 여기에서 하나 이상의 공백이나 쉼표로 정의됩니다.

$ lsdvd -c '/path/to/some/dvd.iso' | \
    awk -F' +|,' '/Chapter:/ && /Length:/ { print $5 }'
00:04:59.934
00:04:59.500
00:05:00.000
00:04:59.500
00:05:00.000
00:04:59.500
00:04:59.500
00:05:00.000
00:04:59.500
00:00:00.500
00:02:56.734

관련 정보