Bash-скрипт. Сдвиг секунд

Bash-скрипт. Сдвиг секунд

В bash я не знаю, как это сделать. Мне нужно сделать bash-скрипт. На stdin у меня есть .srt файл субтитров в таком формате:

num
HH:MM:SS,SSS --> HH:MM:SS,SSS
text line 1
text line 2
...

ЧЧ:ММ:СС,ССС начало и конец заголовка текста.

Скрипт должен сдвигать секунды. (может быть + или -)

Пример:

$cat bmt.srt
5
00:01:02,323 --> 00:01:05,572
Hello, my frieds!
6
....

$./shifter.sh +3<mbt.srt
5
00:01:05,323 --> 00:01:08,572
Hello, my frieds!
6

Мне нужно сначала захватить все ЧЧ:ММ:СС и преобразовать их в секунды. Кто-нибудь может сделать это без sed?

решение1

Если файл субтитров не длится более 24 часов, dateдля этого можно использовать:

#!/usr/bin/env bash

set -o errexit -o noclobber -o nounset -o pipefail

date_offset="$1"

shift_date() {
    date --date="$1 $date_offset" +%T,%N | cut -c 1-12
}

while read -r line
do
    if [[ $line =~ ^[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]\ --\>\ [0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]$ ]]
    then
        read -r start_date separator end_date <<<"$line"
        new_start_date="$(shift_date "$start_date")"
        new_end_date="$(shift_date "$end_date")"
        printf "%s %s %s\n" "$new_start_date" "$separator" "$new_end_date"
        echo "New date"
    else
        printf "%s\n" "$line"
    fi
done

По какой-то причине здесь необходимо использовать десятичные числа, но это работает:

$ ./shifter.sh "+3.0 seconds" < bmt.srt
5
00:01:05,323 --> 00:01:08,572
New date
Hello, my frieds!
6

решение2

Решение на Perl. Я не использовал какой-либо классический модуль обработки времени, поскольку обработка миллисекунд, как правило, плохо поддерживается.

#!/usr/bin/perl
use warnings;
use strict;

use constant FACTORS => (60 * 60 * 1000,
                              60 * 1000,
                                   1000,
                                      1);

sub time2ms {
    my $time = shift;
    my ($ms, $i) = (0, 0);
    $ms += (FACTORS)[$i++] * $_ for split /[^0-9]/, $time;
    return $ms;
}


sub ms2time {
    my $ms = shift;
    my $str = q();
    for my $i (0 .. 3) {
                $str .= sprintf +($i == 3 ? '%03d' : '%02d')
                                    . (':', ':', ',', q())[$i],
                                $ms / (FACTORS)[$i];
        $ms = $ms % (FACTORS)[$i];
    }
    return $str;
}


my $diff   = 1000 * shift;
my $TIME_R = qr/[0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}/;
while (<>) {
    if (my ($from, $to) = /($TIME_R) --> ($TIME_R)/) {
        my $i = 0;
        for my $time ($from, $to) {
            $time = time2ms($time) + $diff;
            print ms2time($time), (' --> ', "\n")[$i++];
        }
    } else {
        print;
    }
}

Связанный контент