0

任务:

我得到了一个带有字幕的文件,其中时间非常糟糕。不过都是一样的时间。我想在它们上运行一个脚本来增加/减少一定的时间。我正在尝试通过 linux 中的命令行来执行此操作。所以我正在尝试使用 awk 和/或 sed。不过,我对他们没有经验。

我要更改的字符串如下所示:01:35:12,300

问题:

使用 awk 我设法编写了一个脚本文件,我可以像这样调用它:

awk -f subtitles_shift.awk change="-01:00:11" subtitle_sample

我的脚本基本上做的是:它将文件中的字符串以及作为参数传递的字符串转换为秒。进行更改,转换回字符串,然后再次吐出整个内容。它有效。

但是,唯一的事情是,我现在不知道如何将这些更改写回文件......

我的想法:

我认为,我应该使用 sed 来完成这项工作,因为它允许我写回文件。但是对于 sed,我不知道如何编写这样一个脚本,在应用替换字符串之前对搜索字符串进行计算。

sed 's/..:..:..,.../REPLACEMENT/' <old >new

在将替换字符串返回给 sed 之前,如何对匹配的模式进行所有这些必要的计算?

我希望你明白我的意思...

最后但并非最不重要的:

提前非常感谢!

代码示例——代码示例

这是我的 awk 脚本的主要部分:

# looking for the lines that hold the time strings
/^..:/ {
    # picking the first and third column. These are the times
    start = $1; 
    end   = $3;
    # calculating changes by invoking functions
    start_new = alter_time(start, change, sign);
    end_new   = alter_time(end, change, sign);
}

可能的解决方案

地狱,是的!我可以处理所有内容,对必要的行进行数学运算,然后将所有行写回文件。到目前为止,这似乎有效:

{
    if ($1 ~ /^..:/) {

        start = $1;
        end   = $3;

        start_new = alter_time(start, change, sign);
        end_new   = alter_time(end, change, sign);

        print start_new " --> " end_new > "times.srt";
    } else {
        print $0 > "times.srt";
    }
}
4

2 回答 2

2

您可以使用就地减法,意思是,获取字幕文件,并使用 awk 解析直到达到时间格式,(您已经完成了广告)

然后利用awk语言的时间函数,就地减法替换。

或者,您可以使用这样的东西进行减法,(感谢glenn

awk -v 'time=16:13:04,699' -v "date=$(date +%H:%M:%S)" '
  function abs(x) {return x<0 ? -x : x}
  BEGIN {
    split(time, ary, /[:,]/); t_sec = 3600*ary[1] + 60*ary[2] + ary[3]
    split(date, ary, /:/);    d_sec = 3600*ary[1] + 60*ary[2] + ary[3]
    # output difference in minutes
    print abs(t_sec - d_sec)/60
  }
'

无论如何,我认为你不需要 sed ,祝你好运。

于 2012-12-24T13:21:46.950 回答
1

很可能远非完美。但这是我到目前为止想出的脚本。而且,嘿,它的工作;-)

我的第一个 awk 脚本,顺便说一句,所以请多多包涵,但请随时指出所有弱点...

#!/usr/bin/awk -f

# invoke me like this:
#
# [awk -f] subtitles_shift.awk var="-01:42:09" file.srt
#
# @ var     the shift forward or backward
# @ file    the srt file to be processed
#
# fractions of seconds are ignored. the script gives the 
# following format back:
# HH:MM:SS,000 --> HH:MM:SS,000
# 
# the script saves to a file named times.srt in the
# current directory.

#############################################
# BEGIN
#############################################

BEGIN {
    print "\nstarting script (subtitles_shift.awk):";
    # get the first variable passed
    var = ARGV[1];
    # assign only the value
    split(var, a, "=");
    change = a[2];
    # assign the operation (addition or subtraction)
    sign = check_sign(change);
    # trim a possible sign from the variable
    sub(/^[^0-9]/, "", change);
    print "the time shift will be: " , sign change;
    print "--------------------------------------";
}

function convert_time_string_to_sec(string) 
{
    # string should be of the format 00:00:00,0[00]
    split(string, a, ":");
    split(a[3], b, ",");
    hh = a[1];
    mm = a[2];
    ss = b[1];
    # calculate the total time in seconds
    return ( hh * 3600 + mm * 60 + ss );
}

function add_leading_zero(str)
{
    if (length(str) == 1) {
        str = ( "0" str );
    }
    return str;
}

function trim_fraction(str)
{
    split(str, array, ".");
    return array[1];
}

function convert_sec_to_string(sec)
{
    # get hours as a fraction
    hours  = sec / 3600;
    # only take complete hours
    h  = trim_fraction(hours);
    # add a leading zero (if necessary)
    hh = add_leading_zero(h);
    # subtract full hours from sec
    sec -= ( h * 3600 );
    # get minutes as a fraction
    min  = sec / 60;
    # only take complete minutes
    m  = trim_fraction(min);
    # add a leading zero (if necessary)
    mm = add_leading_zero(m);
    # subtract full minutes from sec
    sec -= ( m * 60 );
    # add a leading zero (if necessary)
    ss = add_leading_zero(sec);
    # prepare full string and return it
    string = ( hh ":" mm ":" ss ",000" );
    return string;
}

function alter_time(time_str, alter_str, sign)
{
    # get time in seconds
    sec = convert_time_string_to_sec(time_str);
    dif = convert_time_string_to_sec(alter_str);
    # add or subtract according to sign
    if (sign == "+") {
        new = sec + dif;
    } else {
        new = sec - dif;
    }
    # convert back to a string (00:00:00,000) and return
    newstr = convert_sec_to_string(new);
    return newstr;
}

function check_sign(str)
{
    # check for a sign, if none assume addition
    first  = substr(str, 0, 1);
    if (first == "-")
        return "-";
    else
        return "+";
}

#############################################
# main block
#############################################

{
    # if the line starts with time string
    if ($1 ~ /^..:/) {
        # assign start and end time
        start = $1;
        end   = $3;
        # run the main function to change according to argument passed
        start_new = alter_time(start, change, sign);
        end_new   = alter_time(end, change, sign);
        # print the new line to file (string --> string)
        print start_new " --> " end_new > "times.srt";
    } else {
        line = $0;
        # trim line feeds (appeared on my linux machine ^M at eol)
        gsub(/[:\015]/, "", line);
        # print the line to file
        print line > "times.srt";
    }
}

#############################################
# END
#############################################

END {
    print "file times.srt created.";
    print "--------------------------------------";
}
于 2012-12-24T16:59:34.013 回答