Batch file 批处理-如何对时间代码执行数学运算?

Batch file 批处理-如何对时间代码执行数学运算?,batch-file,awk,sed,cygwin,gnu,Batch File,Awk,Sed,Cygwin,Gnu,我一直在编写一个批处理脚本,以更改一些.xml文件的格式/类型 差不多完成了,但我在更改时间代码时遇到了一个问题 这里有一个例子 <Events> <Event In="00:00:20.650" Out="00:00:22.970" <Event In="00:00:23.050" Out="00:00:26.300" 注释 0.025是每毫秒的帧数 帧数必须是整数,不包含任何分数分量 我正在使用GNUWin和Cygwin库工具,所以可以使用bc

我一直在编写一个批处理脚本,以更改一些
.xml
文件的格式/类型

差不多完成了,但我在更改时间代码时遇到了一个问题

这里有一个例子

  <Events>
    <Event In="00:00:20.650" Out="00:00:22.970"
    <Event In="00:00:23.050" Out="00:00:26.300"
注释

  • 0.025是每毫秒的帧数
  • 帧数必须是整数,不包含任何分数分量
  • 我正在使用
    GNUWin
    Cygwin
    库工具,所以可以使用
    bc
    expr
    tr
    awk
    sed
    或任何解决方案来完成工作
使用bc

$ ms="650"
$ ff=$(echo ${ms} "*0.025/1" |bc)
$ echo $ff
16

当结果小于10时,我将留给您添加额外的“0”

您可以使用awk脚本执行此操作:

script.awk

{ 
  re = "[0-9]{2}:[0-9]{2}:[0-9]{2}.([0-9]{3})"
  while( match( $0, re, grps) ) {
    frames = sprintf("%02.0f",( grps[1] *0.025 ) )
    gsub( "." grps[1], ":" frames)
  }
  print
}
像这样运行它
awk-f script.awk yourfile

它尝试匹配这样的时间戳,并将最后一部分(毫秒)捕获到
grps[1]
。然后进行计算,并使用
sprintf
格式化帧


之后,gsub将毫秒替换为帧。

PowerShell:

[xml]$xml=gc events.xml
函数修复([timespan]$ts){
“{0}:{1:D2}”-f$ts.ToString(“hh\:mm\:ss”),[int]($ts.microsides*0.025)
}
$xml.SelectNodes('//Event')|%{
$\.In=fix$\.In
$\输出=修复$\输出
}
$xml.Save(“events\u fixed.xml”)
如果您希望将其作为批处理脚本,可以将其转换为batch+PowerShell polyglot,方法是在顶部插入此脚本并使用.bat扩展名保存:


这是一个纯粹的解决方案。此脚本对所有对
cmd
具有特殊意义的字符都是安全的。基本上,它在给定的输入文件中搜索关键字或属性名
In
Out
,然后搜索
=
和引号
中的时间码。如果找到,毫秒部分将被分割,转换为帧并附加到剩余的时间代码中,由
分隔。每行可以有任意数量的时间代码,只要它们的格式与示例数据中给定的格式相同,并且前面有一个给定的关键字,所有时间代码都会被识别和转换

该脚本支持对转换后的值进行四舍五入--请参见文件开头变量定义公式中的备注(
rem
)(在块中查找备注
此处定义常量:

代码如下:

@echo关闭
setlocal EnableExtensions DisableDelayedExpansion
rem//在此处定义常量:
set KEYWORDS=“In”,“Out”&rem/(提供属性名称列表)
设置“模式=[0-9][0-9]:[0-9][0-9]:[0-9][0-9]。[0-9][0-9][0-9]。”
set/A PLENGTH=12&rem/(解析的'PATTERN'字符串的字符长度)
设置“公式=(MS*25+0)/1000”&rem/*(`+0`表示帧向下取整;
rem使用“+999”进行四舍五入,或使用“+500”进行四舍五入)*/
set/A PADDING=2&rem/(结果帧值的位数)
设置“文件=%~1”
如果未定义文件退出/B 1
对于/F“delims=“%%L in('findstr/N/R“^”“%FILE%”)do(
设置“行=%%L”
setlocal EnableDelayedExpansion
设置“行=!行:*=!”
如果定义行(
对于“!LINE!”中的/F delims^=^eol^=%%E,请执行以下操作(
端部
设置“行=%%E”
setlocal EnableDelayedExpansion
)
)否则(
端部
设置“行=”
setlocal EnableDelayedExpansion
)
对于(!关键字!)中的%%P,请执行以下操作(
端部
设置“关键字=%%~P”
调用:流程行关键字
setlocal EnableDelayedExpansion
)
回声(!线!
端部
)
端部
退出/B
:处理rtn_字符串参考_字符串参考_键
setlocal EnableDelayedExpansion
设置“COLL=”
设置“行=!%~2!”
设置“KEYW=!%~3!”
:循环
如果定义行(
电话:LEN-LLENGTH线路
电话:LEN KLENGTH KEYW
对于/F delims^=^eol^=%%T in(“!KEYW!”)do(
设置“搜索=!行:%%T=!”
)
如有定义,搜索(
如果不是“!SEEK!”==”!LINE!”(
呼叫:LEN SLENGTH SEEK
设置/A T长度=L长度-^(S长度+K长度^)
对于/F“tokens=1,2”%%M in(“!TLENGTH!!KLENGTH!”)执行以下操作(
设置“完成=!行:~,%%M!”
设置“测试=!行:~%%M,%%N!”
)
设置“CHAR=!DONE:~-1!”&设置“CHAR=!CHAR:=!”
设置“完成=!完成:~1!”
如果“!TEST!”==”!KEYW!”(
如果“!CHAR!”==”(
设置“完成=!完成!!键入!”
设置“TEST=!SEEK!”
设置/A t长度=正压+3
对于(“!t长度!”)中的/F%%N,请执行以下操作(
设置“测试=!搜索:~,%%N!”&设置“搜索=!搜索:~%%N!”
)
echo(!TEST!|>nul findstr/R/C:^^^^^^^^^^=\“!PATTERN!\“^^^^^^^^^^^^^^^”
如果不是错误级别1(
对于/F“tokens=1,2 delims=。”%%S in(“!TEST:~1!”)do(
设置“HHMMSS=%%~S”和设置“MS=%%~T”
设置/A“FF=%FORMULA%”
设置“FF=0000!FF!”&设置“FF=!FF:~-%PADDING%”
)
设置“COLL=!COLL!!完成!=”!HHMMSS!:!FF!”&设置“LINE=!SEEK!”
)否则(
设置“COLL=!COLL!!完成!!测试!”&设置“LINE=!SEEK!”
)
)否则(
设置“COLL=!COLL!!完成!!测试!”&设置“LINE=!SEEK!”
)
)否则(
设置“COLL=!COLL!!完成!!测试!”&设置“LINE=!SEEK!”
)
)否则(
设置“COLL=!COLL!!LINE!”&设置“LINE=”
)
)否则(
设置“COLL=!COLL!!LINE!”&设置“LINE=”
)
转到:循环
)
如果定义为COLL(
对于/F delims^=^eol^=%%E in(“!COLL!”)do(
端部
设置“%~1=%%E”
setlocal EnableDelayedExpansion
)
)否则(
恩德罗
{ 
  re = "[0-9]{2}:[0-9]{2}:[0-9]{2}.([0-9]{3})"
  while( match( $0, re, grps) ) {
    frames = sprintf("%02.0f",( grps[1] *0.025 ) )
    gsub( "." grps[1], ":" frames)
  }
  print
}
convert-ms-to-frames.bat "sample.xml" > "return.xml"
<?xml version="1.0"?>
  <Events>
    <Event In="00:00:20.650" Out="00:00:22.970" />
    <Event In="00:00:23.050" Out="00:00:26.300" />
  </Events>
<?xml version="1.0"?>
  <Events>
    <Event In="00:00:20:16" Out="00:00:22:24" />
    <Event In="00:00:23:01" Out="00:00:26:07" />
  </Events>