任务:
我收到了一个带字幕的文件,时间非常糟糕。所有这些都是相同的时间。我想在它们上运行一个脚本来添加/减去一定的时间。我试图通过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";
}
}
答案 0 :(得分:2)
您可以使用就地减法,即获取字幕文件,然后使用awk解析,直至达到时间格式(广告已完成)
然后使用awk语言的time function,在现场减去并替换。
或者,你可以使用这样的东西进行减法,(感谢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,无论如何,祝你好运。
答案 1 :(得分: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 "--------------------------------------";
}