[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文本处理] 批处理如何计算时间差?

本帖最后由 娜美 于 2023-3-20 17:24 编辑

UTF-8 编码文本
a.txt
使用b文本的上下2行数字去循环查找a文本中第3列的上下行数字顺序是否匹配
如, 在b文本的上下2行为1组数字, 用空行分隔视为1组,  
如下面1 2去循环匹配a文本中第3列的上下行是否为1  2   
再用另一个2  3去循环匹配a文本中第3列的上下行是否为2  3
如果a文本第3列可以匹配到b文本的上下2行数字 , 而且他们时间相同, 测返回 OK ,   如果他们时间不相同, 则需要计算出他们的时间间隔,  精度单位为 秒
b.txt
Thanks
移步原文件下载
https://wwkt.lanzoul.com/iq9h80qies0h

本帖最后由 77七 于 2023-3-19 19:42 编辑
  1. @echo off
  2. rem 文件夹不要存在 1.txt 2.txt
  3. setlocal enabledelayedexpansion
  4. for /f "tokens=1-4 delims=        " %%a in (a.txt) do (
  5.         if defined str (
  6.                 >>1.txt echo !str!#%%a#%%b@%%c##%%d
  7.                 set "str=%%a#%%b@@%%c##%%d"
  8.         ) else (
  9.                 set "str=%%a#%%b@@%%c##%%d"
  10.         )
  11. )
  12. set str=
  13. for /f "delims=" %%a in (b.txt) do (
  14.         if defined str (
  15.                 >>2.txt echo !str! %%a
  16.                 set str=
  17.         ) else (
  18.                 set "str=%%a"
  19.         )
  20. )
  21. endlocal
  22. setlocal enabledelayedexpansion
  23. for /f "tokens=1-2" %%a in (2.txt) do (
  24.         for /f "tokens=2,6 delims=中#" %%c in ('type "1.txt" ^| findstr "@@%%a" ^| findstr "@%%b"') do (
  25.                 set "t1=%%c"
  26.                 set "t2=%%d"
  27.                 set "t1=!t1:Mar=3!"
  28.                 set "t2=!t2:Mar=3!"
  29.                 rem 如果需要可以把12个月份的英文都替换为数字
  30.                 for /f "tokens=1-4 delims=,. " %%i in ("!t1!") do (
  31.                         set "t1date=%%k-%%i-%%j %%l"
  32.                 )
  33.                 for /f "tokens=1-4 delims=,. " %%i in ("!t2!") do (
  34.                         set "t2date=%%k-%%i-%%j %%l"
  35.                 )
  36.                 if "!t1date!" equ "!t2date!" (
  37.                         echo 计算列%%a%%b 时差间隔: OK
  38.                 ) else if "!t1date!" gtr "!t2date!" (
  39.                         call :t "!t2date!" "!t1date!"
  40.                         echo 计算列%%a%%b 时差间隔: !secs!秒
  41.                 ) else (
  42.                         call :t "!t1date!" "!t2date!"
  43.                         echo 计算列%%a%%b 时差间隔: !secs!秒
  44.                 )
  45.         )
  46. )>>c2.txt
  47. endlocal
  48. pause
  49. exit
  50. :t
  51. ::日期时间差 code by foxjl
  52. rem set /p date1=输入开始日期(如1984-2-22 5:11:3):
  53. rem set /p date2=输入结束日期(如2013-9-18 5:6:31):
  54. set date1=%~1
  55. set date2=%~2
  56. for /f "tokens=1,2,3,4,5,6,7 delims=-/:. " %%i in ("%date1%") do ((set Y1=%%i) && (set M1=%%j) && (set D1=%%k) && (set H1=%%l) && (set F1=%%m) && (set S1=%%n) && (set MS1=%%o))
  57. for /f "tokens=1,2,3,4,5,6,7 delims=-/:. " %%i in ("%date2%") do ((set Y2=%%i) && (set M2=%%j) && (set D2=%%k) && (set H2=%%l) && (set F2=%%m) && (set S2=%%n) && (set MS2=%%o))
  58. set /a secs=((d2-32075+1461*(y2+4800+(m2-14)/12)/4+367*(m2-2-(m2-14)/12*12)/12-3*((y2+4900+(m2-14)/12)/100)/4)*86400+H2*3600+F2*60+S2)-((d1-32075+1461*(y1+4800+(m1-14)/12)/4+367*(m1-2-(m1-14)/12*12)/12-3*((y1+4900+(m1-14)/12)/100)/4)*86400+H1*3600+F1*60+S1)
  59. rem set /a D=secs/86400,H=(secs%%86400)/3600,M=(secs%%3600)/60,S=secs%%60
  60. rem echo.&echo.%date1%与%date2%之间相隔:%D%天%H%时%M%分%S%秒
  61. rem echo %secs%
  62. exit /b
复制代码

试试这样行吗?字符串比较不太熟悉,很多地方不知道写的对不对
1

评分人数

bat小白,请多指教!谢谢!

TOP

如果a.txt里的**表示的内容不确定,可以预先处理一遍,删除掉
bat小白,请多指教!谢谢!

TOP

本帖最后由 娜美 于 2023-3-20 17:21 编辑

@77七   Thanks
偿试执行了一下
  1. @echo off
  2. rem 文件夹不要存在 1.txt 2.txt
  3. setlocal enabledelayedexpansion
  4. for /f "tokens=1-4 delims= " %%a in (a.txt) do (
  5. if defined str (
  6. >>1.txt echo !str!#%%a#%%b@%%c##%%d
  7. set "str=%%a#%%b@@%%c##%%d"
  8. ) else (
  9. set "str=%%a#%%b@@%%c##%%d"
  10. )
  11. )
  12. set str=
  13. for /f "delims=" %%a in (b.txt) do (
  14. if defined str (
  15. >>2.txt echo !str! %%a
  16. set str=
  17. ) else (
  18. set "str=%%a"
  19. )
  20. )
  21. endlocal
  22. setlocal enabledelayedexpansion
  23. for /f "tokens=1-2" %%a in (2.txt) do (
  24. for /f "tokens=2,6 delims=中#" %%c in ('type "1.txt" ^| findstr "@@%%a" ^| findstr "@%%b"') do (
  25. set "t1=%%c"
  26. set "t2=%%d"
  27. set "t1=!t1:Mar=3!"
  28. set "t2=!t2:Mar=3!"
  29. rem 如果需要可以把12个月份的英文都替换为数字
  30. for /f "tokens=1-4 delims=,. " %%i in ("!t1!") do (
  31. set "t1date=%%k-%%i-%%j %%l"
  32. )
  33. for /f "tokens=1-4 delims=,. " %%i in ("!t2!") do (
  34. set "t2date=%%k-%%i-%%j %%l"
  35. )
  36. if "!t1date!" equ "!t2date!" (
  37. echo 计算列%%a%%b 时差间隔: OK
  38. ) else if "!t1date!" gtr "!t2date!" (
  39. call :t "!t2date!" "!t1date!"
  40. echo 计算列%%a%%b 时差间隔: !secs!秒
  41. ) else (
  42. call :t "!t1date!" "!t2date!"
  43. echo 计算列%%a%%b 时差间隔: !secs!秒
  44. )
  45. )
  46. )>>c2.txt
  47. endlocal
  48. pause
  49. :t
  50. ::日期时间差 code by foxjl
  51. rem set /p date1=输入开始日期(如1984-2-22 5:11:3):
  52. rem set /p date2=输入结束日期(如2013-9-18 5:6:31):
  53. set date1=%~1
  54. set date2=%~2
  55. for /f "tokens=1,2,3,4,5,6,7 delims=-/:. " %%i in ("%date1%") do ((set Y1=%%i) && (set M1=%%j) && (set D1=%%k) && (set H1=%%l) && (set F1=%%m) && (set S1=%%n) && (set MS1=%%o))
  56. for /f "tokens=1,2,3,4,5,6,7 delims=-/:. " %%i in ("%date2%") do ((set Y2=%%i) && (set M2=%%j) && (set D2=%%k) && (set H2=%%l) && (set F2=%%m) && (set S2=%%n) && (set MS2=%%o))
  57. set /a secs=((d2-32075+1461*(y2+4800+(m2-14)/12)/4+367*(m2-2-(m2-14)/12*12)/12-3*((y2+4900+(m2-14)/12)/100)/4)*86400+H2*3600+F2*60+S2)-((d1-32075+1461*(y1+4800+(m1-14)/12)/4+367*(m1-2-(m1-14)/12*12)/12-3*((y1+4900+(m1-14)/12)/100)/4)*86400+H1*3600+F1*60+S1)
  58. rem set /a D=secs/86400,H=(secs%%86400)/3600,M=(secs%%3600)/60,S=secs%%60
  59. rem echo.&echo.%date1%与%date2%之间相隔:%D%天%H%时%M%分%S%秒
  60. rem echo %secs%
  61. exit /b
复制代码
格式基本正确,  只是计算时间差秒数结果值不准确

如果忽略年月日,  是否会可以计算出正确时间差秒数 ?
例如
年月日可以忽略他们不处理,  仅需要对时间组处理是否会简单一些 ?
只需要计算他们时间差   年月日可以忽略

有星号这一列完全可以忽略他们, 因为它在最后一列, 对处理数据应该没有影响

TOP

  1. #@&cls&powershell -sta "gc '%~f0'|out-string|iex"&pause&exit
  2. $a=(gc -enc utf8 a.txt) -join "`n"
  3. (gc b.txt) -join "`n" -split "`n`n"|%{
  4.     $b=$_ -split "`n"
  5.     [regex]::matches($a,'(^|\n)[^\t]+\t([^\t]+)\s\S+\t' + $b[0] + '[^\n]+\1[^\t]+\t([^\t]+)\s\S+\t' + $b[1])|%{
  6. $c=[datetime]$_.Groups[3].value-[datetime]$_.Groups[2].value
  7. if($c.seconds -eq 0){
  8.             "计算列: {0}{1}`t`t时差间隔: {2}" -f $b[0],$b[1],'OK'
  9. }else{
  10.             "计算列: {0}{1}`t`t时差间隔: {2}秒" -f $b[0],$b[1],$c.seconds
  11. }
  12.         ''
  13.     }
  14. }|sc c.txt
复制代码

TOP

本帖最后由 娜美 于 2023-3-20 17:20 编辑

回复 5# idwma

@idwma 哥哥的比较简单直接  格式及计算秒数基本正确 Good
但如果是这样结构似乎会多计算一些重复行,    似乎是最后一列如果是数字2或3 会影响到处理数据
请注意: 复制以下数据到文本后某些列tab键符变成空格,  需要将分隔符还原到样本格式处理
如果可以希望可以批量同时处理多个文件,  处理后的和原文件名称相同,  只是在后面增加txt后辍即可  Thanks idwma 哥哥

TOP

本帖最后由 idwma 于 2023-3-19 22:20 编辑

回复 6# 娜美

第五行改一下
    [regex]::matches($a,'(^|\n)[^\t]+\t([^\t]+)\s\S+\t' + $b[0] + '[^\n]+\1[^\t]+\t([^\t]+)\s\S+\t' + $b[1] + '[^\n]+‘)

多个文件是什么样的

TOP

回复 4# 娜美

2楼代码实测把a.txt保存为ansi可以得到正确结果可能我用了 汉字作为分隔符,出现了问题,现修改如下,应该支持utf-8了
   将第24行改为
  1.         for /f "tokens=2,6 delims=.#" %%c in ('type "1.txt" ^| findstr "@@%%a" ^| findstr "@%%b"') do (
复制代码
bat小白,请多指教!谢谢!

TOP

本帖最后由 terse 于 2023-3-20 16:13 编辑

纯P
修改关于时间的算法,现在按1970.1.1的时间为基数,之前的可能出错
  1. @echo off&setlocal enabledelayedexpansion
  2. rem 存为ANSI码
  3. set /a "Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12"
  4. set "d=(36525*(y+4716)/100+306001*(m+1)/10000+10%%%%b%%100-2442125)"
  5. set "s=(10%%d%%100)*3600+(10%%e%%100)*60+(10%%f%%100)"
  6. set "bs=#"
  7. for /f "delims=" %%i in (b.txt) do (
  8.      if defined b (
  9.         set bs=!bs!!b!%%i#
  10.         set "b="
  11.      ) else set b=%%i
  12. )
  13. for /f "delims=" %%f in ('dir /b /a-d *.txt') do (
  14.      (for /f "usebackq tokens=2,3,5 delims= ,." %%a in ("%%f") do (
  15.           for %%i in ("!a!%%c") do  if not "!bs!" == "!bs:#%%~i#=!" (
  16.                 if not "!str!" == "%%a%%b" (
  17.                     set t=0
  18.                     for %%m in ("%%a%%b" "!str!" ) do (
  19.                           for /f " tokens=1-6 delims=: " %%a in (%%m) do (
  20.                                set /a "m=(%%a+9)%%12+3,y=%%c-m/13"
  21.                                 if !t! == 0 (
  22.                                    set /a "t=%d%*86400+%s%"
  23.                                 ) else set /a "t-=%d%*86400+%s%"
  24.                           )
  25.                     )
  26.                 echo;计算列: !a!%%c 时差间隔: !t!秒
  27.                 ) else echo;计算列: !a!%%c 时差间隔: OK
  28.           )
  29.           set "a=%%c"
  30.           set "str=%%a%%b"
  31.       ))>%%f.tmp
  32. )
  33. pause
复制代码

TOP

回复 4# 娜美


   我重新贴一遍吧,把*那列忽略掉,如果含有@#.都会有影响,我是把两行合并成一行了
  1. @echo off
  2. rem 文件夹不要存在 1.txt 2.txt
  3. setlocal enabledelayedexpansion
  4. for /f "tokens=1-4 delims= " %%a in (a.txt) do (
  5.         if defined str (
  6.                 >>1.txt echo !str!#%%a#%%b@%%c##1
  7.                 set "str=%%a#%%b@@%%c##1"
  8.         ) else (
  9.                 set "str=%%a#%%b@@%%c##1"
  10.         )
  11. )
  12. set str=
  13. for /f "delims=" %%a in (b.txt) do (
  14.         if defined str (
  15.                 >>2.txt echo !str! %%a
  16.                 set str=
  17.         ) else (
  18.                 set "str=%%a"
  19.         )
  20. )
  21. endlocal
  22. setlocal enabledelayedexpansion
  23. for /f "tokens=1-2" %%a in (2.txt) do (
  24.         for /f "tokens=2,6 delims=.#" %%c in ('type "1.txt" ^| findstr "@@%%a" ^| findstr "@%%b"') do (
  25.                 set "t1=%%c"
  26.                 set "t2=%%d"
  27.                 set "t1=!t1:Mar=3!"
  28.                 set "t2=!t2:Mar=3!"
  29.                 rem 如果需要可以把12个月份的英文都替换为数字
  30.                 for /f "tokens=1-4 delims=,. " %%i in ("!t1!") do (
  31.                         set "t1date=%%k-%%i-%%j %%l"
  32.                 )
  33.                 for /f "tokens=1-4 delims=,. " %%i in ("!t2!") do (
  34.                         set "t2date=%%k-%%i-%%j %%l"
  35.                 )
  36.                 if "!t1date!" equ "!t2date!" (
  37.                         echo 计算列%%a%%b 时差间隔: OK
  38.                 ) else if "!t1date!" gtr "!t2date!" (
  39.                         call :t "!t2date!" "!t1date!"
  40.                         echo 计算列%%a%%b 时差间隔: !secs!秒
  41.                 ) else (
  42.                         call :t "!t1date!" "!t2date!"
  43.                         echo 计算列%%a%%b 时差间隔: !secs!秒
  44.                 )
  45.         )
  46. )>>c2.txt
  47. endlocal
  48. pause
  49. exit
  50. :t
  51. ::日期时间差 code by foxjl
  52. rem set /p date1=输入开始日期(如1984-2-22 5:11:3):
  53. rem set /p date2=输入结束日期(如2013-9-18 5:6:31):
  54. set date1=%~1
  55. set date2=%~2
  56. for /f "tokens=1,2,3,4,5,6,7 delims=-/:. " %%i in ("%date1%") do ((set Y1=%%i) && (set M1=%%j) && (set D1=%%k) && (set H1=%%l) && (set F1=%%m) && (set S1=%%n) && (set MS1=%%o))
  57. for /f "tokens=1,2,3,4,5,6,7 delims=-/:. " %%i in ("%date2%") do ((set Y2=%%i) && (set M2=%%j) && (set D2=%%k) && (set H2=%%l) && (set F2=%%m) && (set S2=%%n) && (set MS2=%%o))
  58. set /a secs=((d2-32075+1461*(y2+4800+(m2-14)/12)/4+367*(m2-2-(m2-14)/12*12)/12-3*((y2+4900+(m2-14)/12)/100)/4)*86400+H2*3600+F2*60+S2)-((d1-32075+1461*(y1+4800+(m1-14)/12)/4+367*(m1-2-(m1-14)/12*12)/12-3*((y1+4900+(m1-14)/12)/100)/4)*86400+H1*3600+F1*60+S1)
  59. rem set /a D=secs/86400,H=(secs%%86400)/3600,M=(secs%%3600)/60,S=secs%%60
  60. rem echo.&echo.%date1%与%date2%之间相隔:%D%天%H%时%M%分%S%秒
  61. rem echo %secs%
  62. exit /b
复制代码
bat小白,请多指教!谢谢!

TOP

本帖最后由 娜美 于 2023-3-20 00:09 编辑

@terse     @idwma    @77七    都ok哦 thanks
现有350个文件需要处理, 一个一个处理感觉挺麻烦,  想批量同时处理多个文件, 各个文件数据格式都相同,  处理后文件名需要和原文件名称相同,

a.txt
2.txt

处理好的各个文件后缀用tmp就行
a.txt.tmp
2.txt.tmp

TOP

回复 11# 娜美
已修改 另外处理时间换个算法 原来的怕有误

TOP

回复 12# terse


    Good 多谢哥哥

TOP

返回列表