Board logo

标题: [文本处理] 批处理for中tokens=变量不可为动态时如何处理数据? [打印本页]

作者: yakeyun    时间: 2024-6-25 22:21     标题: 批处理for中tokens=变量不可为动态时如何处理数据?

现有CinebenchR23程序日志某段信息如下:
    Framework        : OpenGL
    Vendor           : ATI Technologies Inc. (AMD)
    Renderer         : AMD Radeon RX 6600 LE
    Framework version: 4.6.0 Compatibility Profile Context 24.2.1.240215
    Driver version   : 23.40.19.01-240215a1-400566C-AMD-Software-Adrenalin-Edition
CINEBENCH AUTORUN
Please wait until all tests are done!

Warning: Unknown arguments: -g_CinebenchCpuXTest=true
Warning: Unknown arguments: -g_CinebenchCpuXTest=true

来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128
Running Multiple CPU Render Test...
Minimum test duration: 600000.0 ms seconds.
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128

127.0.0.1 的 Ping 统计信息:
    数据包: 已发送 = 5,已接收 = 5,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 0ms,最长 = 0ms,平均 = 0ms
瀹屾垚
请按任意键继续. . . Rendering...
Values: {13474.483} -> Avg/Deviation: 13474.483/0.000
Values: {13474.483,12739.790} -> Avg/Deviation: 13107.136/367.346
Values: {13474.483,12739.790,12486.068} -> Avg/Deviation: 12900.114/419.141
Values: {13474.483,12739.790,12486.068,12450.031} -> Avg/Deviation: 12787.593/411.997
Values: {13474.483,12739.790,12486.068,12450.031,12453.352} -> Avg/Deviation: 12720.745/392.005
Values: {13474.483,12739.790,12486.068,12450.031,12453.352,12381.667} -> Avg/Deviation: 12664.232/379.507
Values: {13474.483,12739.790,12486.068,12450.031,12453.352,12381.667,12364.501} -> Avg/Deviation: 12621.413/366.676
Values: {13474.483,12739.790,12486.068,12450.031,12453.352,12381.667,12364.501,12430.922} -> Avg/Deviation: 12597.602/348.731
Values: {13474.483,12739.790,12486.068,12450.031,12453.352,12381.667,12364.501,12430.922,12430.922} -> Avg/Deviation: 12579.082/332.934
Values: {13474.483,12739.790,12486.068,12450.031,12453.352,12381.667,12364.501,12430.922,12430.922,12366.235} -> Avg/Deviation: 12557.797/322.239
CB 12557.80 (0.00)

请教如何获取“,”和“}”信息中间的信息1,“:” 和“/”中间的信息2,以及最后面“/”后的数值,获取最终数值如下:
数值1:13474.483_数值2:13474.483_数值3:0.000
数值1:12739.790_数值2:13107.136_数值3:367.346
数值1:12486.068_数值2:12900.114_数值3:419.141


原本用下面代码是可以实现的,但是由于for中tokens不可为动态变量,导致运行出错。
  1. @echo off & setlocal enabledelayedexpansion
  2. cd /d "%~dp0"
  3. set "count=1"
  4. for /f "tokens=%n%,6-7 delims={}:^/"  %%a in ('type "R23日志.txt" ^| find /i "Values"') do (
  5. set /a "count+=1"
  6. echo 第!count!轮CPU参考分数:%%a___实际跑分:%%b___跑分差值:%%c
  7. )
  8. :end
  9. echo.
  10. echo CPU稳定性测试完成!
  11. echo.
  12. pause
复制代码
这个是日志下载地址:
https://sanli.lanzoue.com/b0foko6xi
密码:dvrj
作者: ShowCode    时间: 2024-6-25 23:02

回复 1# yakeyun
  1. @echo off
  2. cd /d "%~dp0"
  3. setlocal enabledelayedexpansion
  4. set "count=1"
  5. for /f "tokens=2-3 delims={}" %%i in ('type "R23日志.txt" ^| find /i "Values"') do (
  6.     set /a "count+=1"
  7.     for %%a in (%%i) do (
  8.         set "ScoreRefer=%%a"
  9.     )
  10.     for /f "tokens=4-5 delims=/ " %%a in ("%%j") do (
  11.         set "ScoreActual=%%a"
  12.         set "ScoreMinus=%%b"
  13.     )
  14.     echo 第!count!轮CPU参考分数:!ScoreRefer!___实际跑分:!ScoreActual!___跑分差值:!ScoreMinus!
  15. )
  16. pause
复制代码

作者: aloha20200628    时间: 2024-6-26 14:30

回复 1# yakeyun

已用一楼示例样本测试通过...
  1. @echo off &setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (' findstr /ic:"Values:" "R23日志.txt" ') do (
  3. set/a "n+=1" & set a="%%a/"
  4. for /f "tokens=2 delims={}" %%m in ("%%~a") do for %%v in (%%m) do set "v1=%%v"
  5. for /f "tokens=1-2 delims=/" %%b in ("!a:*Deviation: =!") do (
  6. echo,第!n!轮CPU参考分数:!v1!___实际跑分:%%b___跑分差值:%%c
  7. )
  8. )
  9. endlocal&pause&exit/b
复制代码

作者: qixiaobin0715    时间: 2024-6-26 15:49

批处理文件保存为ANSI编码:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "tokens=2,4 delims=:{}-> " %%i in ('type "R23日志.txt"^|findstr /bi Values:') do (
  4.     set /a n+=1
  5.     for %%a in (%%i) do set value1=%%a
  6.     for /f "tokens=1,2 delims=/" %%b in ("%%j") do (echo,第!n!轮CPU参考分数:!value1!___实际跑分:%%b___跑分差值:%%c)
  7. )
  8. pause
复制代码

作者: yakeyun    时间: 2024-7-2 12:20

上面几种都可以实现需求数据,但是还是希望能有大佬给出其他思路,看下能否通过TOKENS数值递增获取。
作者: aloha20200628    时间: 2024-7-2 12:57

本帖最后由 aloha20200628 于 2024-7-2 13:45 编辑

回复 5# yakeyun

3楼代码第4行是对{n1,n2,...,ne}花括号中的数列遍历(无论其长度增减)并最终提取最后一个目标值ne;
代码第5行是用关键词 ‘Deviation: ’ 直接锚定其后的 k1/k2 字段,再用分隔符/取出目标值k1和k2。
仅用分隔符界定的字段(token)序号若每次可变,就不能用来唯一性锚定每个目标值,除非其具有自己的专属分隔符,而非与那些非目标值字段共用 ,: / 等分隔符
楼主所谓的改变操作路线,其逻辑步骤能否明确一下...

作者: 77七    时间: 2024-7-2 13:09

2-4楼的方法已经是标准答案了。
楼主的想法是不是这样
  1. @echo off
  2. for /f "tokens=%n%" %%a in ("q w e r") do (
  3. set /a n+=1
  4. echo %%a
  5. )
  6. pause
复制代码


依次输出 q w e r ?

这个是不符合实际的,况且bat中tokens的数量有限制,作为一门易上手的脚本,能够实现需求即可,楼主何必化简为繁呢?
作者: ShowCode    时间: 2024-7-2 13:59

回复 5# yakeyun
  1. @echo off
  2. set "count=0"
  3. cd /d "%~dp0"
  4. setlocal enabledelayedexpansion
  5. for /f "tokens=2,6-7 delims={}:/ " %%a in ('type "R23日志.txt" ^| find /i "Values"') do (
  6.     set /a count+=1
  7.     call :GetRefer "%%a" !count!
  8.     echo 第!count!轮CPU参考分数:!ScoreRefer!___实际跑分:%%b___跑分差值:%%c
  9. )
  10. pause
  11. exit /b
  12. :GetRefer
  13. REM tokens数值递增变动的部分单独拿出来作为子函数被call命令调用
  14. for /f "tokens=%2 delims=," %%h in ("%~1") do (
  15.     set "ScoreRefer=%%h"
  16. )
  17. goto :eof
复制代码

作者: aloha20200628    时间: 2024-7-2 14:32

本帖最后由 aloha20200628 于 2024-7-2 15:30 编辑

回复 5# yakeyun

用{n1,n2,...,ne}遍历方法获取最后目标值ne的令牌序号Qne,再根据与其后k1,k2两个目标值的相对不变位序获取其令牌序号 Qk1,Qk2,批处不支持分割表达式中直接使用延迟变量!v!,就只能丢给子过程 call !Qne! !Qk1! !Qk2! 重新提取三个目标值,也是另一种解法,但步骤会增加,舍简求繁了...

作者: qixiaobin0715    时间: 2024-7-2 15:04

楼主可能是想用一个for循环解决数据提取的问题。
作者: aloha20200628    时间: 2024-7-2 15:10

本帖最后由 aloha20200628 于 2024-7-2 15:14 编辑

回复 5# yakeyun

用9楼的算法给一个新版本,看楼主是否可口...
  1. @echo off &setlocal enabledelayedexpansion &set/a "n=0,i=0"
  2. for /f "delims=" %%a in (' findstr /ic:"Values:" "R23日志.txt" ') do (
  3. for /f "tokens=2 delims={}" %%m in ("%%~a") do for %%v in (%%m) do set/a "i+=1"
  4. set/a "q1=2+i,q2=q1+3,q3=q2+1"
  5. set/a "n+=1" & (call :get3v "%%~a" !n! !q1! !q2! !q3!) &set "i="
  6. )
  7. endlocal&pause&exit/b
  8. :get3v
  9. for /f "tokens=%~3,%~4,%~5 delims=:{,}/" %%a in ("%~1") do (
  10. echo,第%~2轮CPU参考分数:%%a___实际跑分:%%b___跑分差值:%%c
  11. )
  12. exit/b
复制代码

作者: Five66    时间: 2024-7-2 23:39

想要tokens=变量就用call或者套进for /f的command里
还得注意tokens是有上限的
例如下面的 , 请确保tokens确实是这个规律并且不超过上限
  1. @echo off
  2. cd /d "%~dp0"
  3. set "count=1"
  4. set "@value1=3"
  5. set "@value2=6"
  6. set "@value3=7"
  7. for /f "delims="  %%z in ('type "R23日志.txt" ^| find /i "Values"') do (
  8. set "@line=%%z"
  9. set /a "count+=1"
  10. call :aaa
  11. set /a @value1+=1&set /a @value2+=1&set /a @value3+=1
  12. )
  13. echo.
  14. echo CPU稳定性测试完成!
  15. echo.
  16. pause&exit/b
  17. :aaa
  18. setlocal enabledelayedexpansion
  19. for /f "tokens=%@value1%,%@value2%-%@value3% delims={}:^/,"  %%a in ("!@line!") do (
  20. endlocal
  21. echo 第%count%轮CPU参考分数: %%a___实际跑分:%%b___跑分差值: %%c
  22. )
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2