找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 4181|回复: 5

[文本处理] [已解决]求助批处理txt里时间格式的转化和进位问题

[复制链接]
发表于 2025-6-21 20:03:39 | 显示全部楼层 |阅读模式
我的一个txt文件里存储着很多的时长数据,时长是按“小时:分钟:秒.毫秒”的格式存储的。txt里还包含着一些汉字。如下所示:
00:01:04.567        00:01:04.933        00:00:00.367        寒
00:01:59.998        00:01:05.300        00:00:00.997        空
……
现在我的需求是把这个txt里所有的时长数据转化为“分钟:秒:厘秒”的格式(转化后的分钟、秒、厘秒都要求是两位数),替换原始的时间。即把原始的txt转变成下面这样:
01:04:57        01:04:93        00:00:37        寒
02:00:00        01:05:30        00:01:00        空
……

说明:(1)txt中所有时长数据都不超过99分钟,不用考虑第一位分钟的数据超过2位的情况;
(2)在把毫秒化成厘秒时,要求四舍五入。
(3)最主要的难点在于进位。毫秒四舍五入后如果进位,可能会导致分钟数或者秒数变化,这个难点我解决不了,所以来向高手求助,学习一下。
谢谢。

评分

参与人数 1PB +2 收起 理由
Batcher + 2 感谢给帖子标题标注[已解决]字样

查看全部评分

发表于 2025-6-21 21:29:07 | 显示全部楼层
BAT
  1. @echo off
  2. :: 时间格式转换工具(hh:mm:ss.SSS → MM:SS:CC)
  3. :: 支持毫秒四舍五入和自动进位处理
  4. chcp 65001 >nul
  5. setlocal enabledelayedexpansion

  6. :: 检查输入文件
  7. if not exist "input.txt" (
  8.     echo ❌ 错误:找不到 input.txt 文件
  9.     echo 请确保:
  10.     echo 1. 文件与脚本在同一目录
  11.     echo 2. 文件名确认为 input.txt
  12.     pause
  13.     exit /b
  14. )

  15. :: 准备输出文件
  16. if exist "output.txt" del "output.txt"

  17. :: 主处理循环
  18. for /f "usebackq delims=" %%L in ("input.txt") do (
  19.     set "line=%%L"
  20.     set "new_line="
  21.    
  22.     :: 使用令牌循环处理每行内容
  23.     for %%T in (!line!) do (
  24.         set "token=%%T"
  25.         
  26.         :: 检查是否是时间格式 (hh:mm:ss.SSS)
  27.         echo !token!|findstr /r "^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.[0-9][0-9][0-9]$" >nul
  28.         if !errorlevel! equ 0 (
  29.             call :CONVERT_TIME "!token!"
  30.             set "new_line=!new_line! !result!"
  31.         ) else (
  32.             set "new_line=!new_line! !token!"
  33.         )
  34.     )
  35.    
  36.     :: 写入输出文件(去掉行首空格)
  37.     echo !new_line:~1!>>"output.txt"
  38. )

  39. echo ✅ 转换完成!结果已保存到 output.txt
  40. pause
  41. exit /b

  42. :: 精确时间转换函数(支持四舍五入和自动进位)
  43. :CONVERT_TIME
  44. set "time_str=%~1"

  45. :: 提取各部分(保持前导零)
  46. set "h=!time_str:~0,2!"
  47. set "m=!time_str:~3,2!"
  48. set "s=!time_str:~6,2!"
  49. set "ms=!time_str:~9,3!"

  50. :: 转换为数值(去除前导零)
  51. for /f "tokens=* delims=0" %%a in ("!h!") do set /a h=%%a
  52. for /f "tokens=* delims=0" %%a in ("!m!") do set /a m=%%a
  53. for /f "tokens=* delims=0" %%a in ("!s!") do set /a s=%%a
  54. for /f "tokens=* delims=0" %%a in ("!ms!") do set /a ms=%%a

  55. :: 处理空值(全零情况)
  56. if "!h!"=="" set /a h=0
  57. if "!m!"=="" set /a m=0
  58. if "!s!"=="" set /a s=0
  59. if "!ms!"=="" set /a ms=0

  60. :: 计算总毫秒数(关键步骤)
  61. set /a total_ms=h*3600000 + m*60000 + s*1000 + ms

  62. :: 毫秒转厘秒(四舍五入)
  63. set /a centiseconds=(total_ms + 5) / 10

  64. :: 计算最终时间(自动处理进位)
  65. set /a total_seconds=centiseconds / 100
  66. set /a cs=centiseconds %% 100
  67. set /a minutes=total_seconds / 60
  68. set /a seconds=total_seconds %% 60

  69. :: 处理进位后可能的60秒情况(如 59.995秒 → 应进位为1分钟0秒)
  70. if !seconds! geq 60 (
  71.     set /a minutes+=1
  72.     set /a seconds-=60
  73. )

  74. :: 两位数格式化
  75. set "minutes=0!minutes!"
  76. set "minutes=!minutes:~-2!"
  77. set "seconds=0!seconds!"
  78. set "seconds=!seconds:~-2!"
  79. set "cs=0!cs!"
  80. set "cs=!cs:~-2!"

  81. set "result=!minutes!:!seconds!:!cs!"
  82. goto :EOF
复制代码
PS1
  1. # 设置默认编码为 UTF-8(避免中文乱码)
  2. $OutputEncoding = [System.Text.Encoding]::UTF8
  3. try {
  4.     [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
  5. } catch {
  6.     Write-Host "⚠️ 无法设置控制台输出编码(不影响脚本功能)" -ForegroundColor Yellow
  7. }

  8. # 获取脚本所在目录
  9. $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition

  10. # 输入输出文件路径
  11. $inputFile  = Join-Path $scriptDir "input.txt"
  12. $outputFile = Join-Path $scriptDir "output.txt"

  13. # 如果 output.txt 已存在,先删除
  14. if (Test-Path $outputFile) {
  15.     Remove-Item $outputFile
  16. }

  17. # 检查输入文件是否存在
  18. if (-not (Test-Path $inputFile)) {
  19.     Write-Host "❌ 错误:找不到 input.txt 文件,请确保它和脚本在同一个目录下。" -ForegroundColor Red
  20.     Read-Host "按任意键退出..."
  21.     exit
  22. }

  23. # 定义时间转换函数
  24. function Format-Time([int]$totalMs) {
  25.     $centiseconds = [math]::Round($totalMs / 10)
  26.     $totalSeconds = [math]::Floor($centiseconds / 100)
  27.     $cs = $centiseconds % 100
  28.     $minutes = [math]::Floor($totalSeconds / 60)
  29.     $seconds = $totalSeconds % 60

  30.     # 确保是整数类型
  31.     $minutes = [int]$minutes
  32.     $seconds = [int]$seconds
  33.     $cs = [int]$cs

  34.     # 使用英文双引号 + 正确格式化
  35.     return "{0:D2}:{1:D2}:{2:D2}" -f $minutes, $seconds, $cs
  36. }

  37. # 逐行处理文本
  38. Get-Content -Path $inputFile -Encoding UTF8 | ForEach-Object {
  39.     $line = $_

  40.     # 使用正则替换所有 hh:mm:ss.SSS 时间格式
  41.     $newLine = [regex]::Replace($line, '\b(\d{2}):(\d{2}):(\d{2})\.(\d{3})\b', {
  42.         param($match)

  43.         # 提取各部分并转为整数
  44.         $parts = $match.Value -split '[:.]'
  45.         $h = [int]$parts[0]
  46.         $m = [int]$parts[1]
  47.         $s = [int]$parts[2]
  48.         $ms = [int]$parts[3]

  49.         # 计算总毫秒
  50.         $totalMs = $h * 3600000 + $m * 60000 + $s * 1000 + $ms

  51.         # 格式化为 MM:SS:CC
  52.         return Format-Time $totalMs
  53.     })

  54.     # 写入输出文件(使用 UTF-8 编码)
  55.     Add-Content -Path $outputFile -Value $newLine -Encoding UTF8
  56. }

  57. Write-Host "✅ 转换完成,结果已写入 output.txt" -ForegroundColor Green
  58. Read-Host "按任意键退出..."
复制代码

评分

参与人数 1技术 +1 收起 理由
vicodin + 1 很整齐的代码,感谢分享。

查看全部评分

发表于 2025-6-21 22:25:10 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-6-21 23:09 编辑

回复 1# vicodin

以下代码存为 test.bat 运行,与源文件(假设名为 t.txt,可自定义)同目录,输出文件名为 t.new.txt(可自定义)...

  1. @echo off &setlocal & (for /f "tokens=1-4 delims=         " %%a in (t.txt) do (
  2.    for %%t in (%%a,%%b,%%c) do for /f "tokens=1-3 delims=:" %%x in ("%%t") do for /f "tokens=1-4 delims=:" %%A in ('powershell "$t=3600*%%x+60*%%y+%%z;$t=[math]::round($t,2);[timespan]::fromseconds($t).tostring('hh\:mm\:ss\:ff')" ') do (
  3.    if %%A gtr 0 (set/a _#m=60*%%A+%%B) else set "_#m=%%B"
  4.    for /f "tokens=2 delims==" %%m in ('set _#m') do set/p="%%m:%%C:%%D        "<nul)
  5. ) &echo,%%d)>"t.new.txt"
  6. type "t.new.txt" &pause&exit/b
复制代码

评分

参与人数 1技术 +1 收起 理由
vicodin + 1 感谢

查看全部评分

发表于 2025-6-21 23:53:17 | 显示全部楼层
  1. powershell "type 123.txt|foreach{[regex]::replace($_,'[\d:.]+?(\d)\s',{$i=$args[0];$t=[timespan]$i.value;if($i.groups[1].value-ge5){$t+=[timespan]100000};'{0:hh\:mm\:ss\:ff}'-f$t})}"
复制代码

评分

参与人数 1技术 +1 收起 理由
vicodin + 1 简洁

查看全部评分

发表于 2025-6-22 03:25:41 | 显示全部楼层
  1. @echo off
  2. cd /d "%~dp0"
  3. for /f "useback tokens=1-3*" %%o in ("1.txt") do (
  4.         set str=%%r
  5.         setlocal enabledelayedexpansion
  6.         for %%i in ("%%o" "%%p" "%%q") do (
  7.                 for /f "tokens=1-4 delims=:." %%a in ("%%~i") do (
  8.                         set /a "s=(1%%a-100)*3600+(1%%b-100)*60+(1%%c-100)+(m=1%%d+5)/2000,n1=100+s/60,n2=100+s%%60"
  9.                         set /p="!n1:~-2!:!n2:~-2!:!m:~1,2!        "<nul
  10.                 )
  11.         )
  12.         echo=!str!
  13.         endlocal
  14. )
  15. pause
复制代码

评分

参与人数 1技术 +1 收起 理由
vicodin + 1 感谢

查看全部评分

发表于 2025-6-22 16:10:21 | 显示全部楼层
回复 1# vicodin

3楼代码在循环体内逐行调用 powershell 处理,效率不理想,改用 bat+powershell 混编版式,让 powershell 一次性解决问题,依然保持3楼代码的兼容性》一。兼容源文件每行字段分割符可以是空格或制表符;二。源文件中的字段如 01:25:03.997 的处理结果为 85:04:00。以下代码存为 test.bat 运行,与源文件(代码预设名为 t.txt,输出结果文件名为 t.new.txt)同目录...

  1. <# ::
  2. @echo off &powershell "iex(${%~f0}|out-string)">"t.new.txt" &type "t.new.txt" &exit/b
  3. #>
  4. gc t.txt | % {
  5.   $l=$_.split(" `t",[StringSplitOptions]::RemoveEmptyEntries); $tt='';
  6.   $l[0..($l.length-2)] | % {
  7.     $t=$_.split(':'); $s=3600*$t[0]+60*$t[1]+$t[2]; $s=[math]::round($s,2);
  8.     $t=[timespan]::fromseconds($s).tostring('hh\:mm\:ss\:ff').split(':');
  9.     $m=60*$t[0]+$t[1]; $m='{0:d2}'-f $m; $t=''+$m+':'+$t[2]+':'+$t[3]; $tt+=$t+"`t"; }
  10.   $tt+$l[$l.length-1]; }; exit
复制代码

评分

参与人数 1技术 +1 收起 理由
vicodin + 1 赞!好用

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 07:06 , Processed in 0.040257 second(s), 17 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表