Bash-script. Shift seconds












6















In bash I don't know how to do that. I need to do a bash-script. At stdin I have .srt file of subtitles in this format:



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


HH:MM:SS,SSS start and finish of title for text.



Script must shift seconds. (it can be + or -)



Example:



$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


I need to grab all HH:MM:SS and convert them to seconds firstly. Is somebody able do this without sed?










share|improve this question

























  • mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...

    – frostschutz
    Oct 17 '13 at 20:15
















6















In bash I don't know how to do that. I need to do a bash-script. At stdin I have .srt file of subtitles in this format:



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


HH:MM:SS,SSS start and finish of title for text.



Script must shift seconds. (it can be + or -)



Example:



$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


I need to grab all HH:MM:SS and convert them to seconds firstly. Is somebody able do this without sed?










share|improve this question

























  • mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...

    – frostschutz
    Oct 17 '13 at 20:15














6












6








6


1






In bash I don't know how to do that. I need to do a bash-script. At stdin I have .srt file of subtitles in this format:



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


HH:MM:SS,SSS start and finish of title for text.



Script must shift seconds. (it can be + or -)



Example:



$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


I need to grab all HH:MM:SS and convert them to seconds firstly. Is somebody able do this without sed?










share|improve this question
















In bash I don't know how to do that. I need to do a bash-script. At stdin I have .srt file of subtitles in this format:



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


HH:MM:SS,SSS start and finish of title for text.



Script must shift seconds. (it can be + or -)



Example:



$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


I need to grab all HH:MM:SS and convert them to seconds firstly. Is somebody able do this without sed?







bash shell-script text-processing date






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 18 '18 at 19:19









Rui F Ribeiro

39.6k1479132




39.6k1479132










asked Oct 17 '13 at 20:08









GeorgyGeorgy

514




514













  • mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...

    – frostschutz
    Oct 17 '13 at 20:15



















  • mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...

    – frostschutz
    Oct 17 '13 at 20:15

















mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...

– frostschutz
Oct 17 '13 at 20:15





mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...

– frostschutz
Oct 17 '13 at 20:15










2 Answers
2






active

oldest

votes


















7














Unless the subtitle file spans more than 24 hours, you can use date for this:



#!/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 %sn" "$new_start_date" "$separator" "$new_end_date"
echo "New date"
else
printf "%sn" "$line"
fi
done


For some reason you need to use decimal numbers with this, but it works:



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





share|improve this answer

































    5














    Perl solution. I did not use any classical time handling module, as miliseconds handling is generally poorly supported.



    #!/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;
    }
    }





    share|improve this answer


























    • Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

      – Vangelis Tasoulas
      Jan 6 '14 at 20:07













    • @VangelisTasoulas: Updated.

      – choroba
      Feb 12 '17 at 17:11











    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f96531%2fbash-script-shift-seconds%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    7














    Unless the subtitle file spans more than 24 hours, you can use date for this:



    #!/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 %sn" "$new_start_date" "$separator" "$new_end_date"
    echo "New date"
    else
    printf "%sn" "$line"
    fi
    done


    For some reason you need to use decimal numbers with this, but it works:



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





    share|improve this answer






























      7














      Unless the subtitle file spans more than 24 hours, you can use date for this:



      #!/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 %sn" "$new_start_date" "$separator" "$new_end_date"
      echo "New date"
      else
      printf "%sn" "$line"
      fi
      done


      For some reason you need to use decimal numbers with this, but it works:



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





      share|improve this answer




























        7












        7








        7







        Unless the subtitle file spans more than 24 hours, you can use date for this:



        #!/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 %sn" "$new_start_date" "$separator" "$new_end_date"
        echo "New date"
        else
        printf "%sn" "$line"
        fi
        done


        For some reason you need to use decimal numbers with this, but it works:



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





        share|improve this answer















        Unless the subtitle file spans more than 24 hours, you can use date for this:



        #!/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 %sn" "$new_start_date" "$separator" "$new_end_date"
        echo "New date"
        else
        printf "%sn" "$line"
        fi
        done


        For some reason you need to use decimal numbers with this, but it works:



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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Oct 21 '13 at 7:25

























        answered Oct 17 '13 at 21:08









        l0b0l0b0

        28k17119246




        28k17119246

























            5














            Perl solution. I did not use any classical time handling module, as miliseconds handling is generally poorly supported.



            #!/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;
            }
            }





            share|improve this answer


























            • Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

              – Vangelis Tasoulas
              Jan 6 '14 at 20:07













            • @VangelisTasoulas: Updated.

              – choroba
              Feb 12 '17 at 17:11
















            5














            Perl solution. I did not use any classical time handling module, as miliseconds handling is generally poorly supported.



            #!/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;
            }
            }





            share|improve this answer


























            • Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

              – Vangelis Tasoulas
              Jan 6 '14 at 20:07













            • @VangelisTasoulas: Updated.

              – choroba
              Feb 12 '17 at 17:11














            5












            5








            5







            Perl solution. I did not use any classical time handling module, as miliseconds handling is generally poorly supported.



            #!/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;
            }
            }





            share|improve this answer















            Perl solution. I did not use any classical time handling module, as miliseconds handling is generally poorly supported.



            #!/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;
            }
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Feb 12 '17 at 17:11

























            answered Oct 17 '13 at 22:31









            chorobachoroba

            26.5k44773




            26.5k44773













            • Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

              – Vangelis Tasoulas
              Jan 6 '14 at 20:07













            • @VangelisTasoulas: Updated.

              – choroba
              Feb 12 '17 at 17:11



















            • Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

              – Vangelis Tasoulas
              Jan 6 '14 at 20:07













            • @VangelisTasoulas: Updated.

              – choroba
              Feb 12 '17 at 17:11

















            Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

            – Vangelis Tasoulas
            Jan 6 '14 at 20:07







            Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.

            – Vangelis Tasoulas
            Jan 6 '14 at 20:07















            @VangelisTasoulas: Updated.

            – choroba
            Feb 12 '17 at 17:11





            @VangelisTasoulas: Updated.

            – choroba
            Feb 12 '17 at 17:11


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f96531%2fbash-script-shift-seconds%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

            is 'sed' thread safe

            How to make a Squid Proxy server?