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

回复 1# shenlong

文本行的格式化输出,须确定最大列宽即最大字段长度。简单处理是由楼主预设一个最大列宽值,否则就要实时遍历整个文本文件获取其中最大字段长度...
给一个批处版本,代码如下》获取文本文件中的最大字段长度,假设字段分隔符是批处默认的空格、逗号、分号、等号和制表符。
  1. @echo off &setlocal enabledelayedexpansion &set "maxZ=0"
  2. for /f "delims=" %%a in (1.txt) do for %%s in (%%a) do (
  3. set/p="%%s"<nul>0.0
  4. for %%b in (0.0) do if %%~zb gtr !maxZ! set "maxZ=%%~zb"
  5. )
  6. echo,!maxZ!
  7. del/q "0.0"&endlocal&pause&exit/b
复制代码

TOP

本帖最后由 aloha20200628 于 2024-7-18 12:08 编辑

回复 1# shenlong
  1. @echo off &setlocal enabledelayedexpansion &set "maxZ=0"
  2. for /f "delims=" %%a in (1.txt) do for %%s in (%%a) do (
  3. set "s=%%s" & (call :_strLen s z)
  4. if !z! gtr !maxZ! set "maxZ=!z!"
  5. )
  6. set "ms=" &for /l %%n in (1,1,!maxZ!) do set "ms=!ms! "
  7. endlocal &set "maxZ=%maxZ%"&set "ms=%ms%"
  8. setlocal enabledelayedexpansion
  9. for /f "delims=" %%a in (1.txt) do (
  10. set "s="
  11. for %%s in (%%a) do (set "_s=%%s"&set "_s=!_s!%ms%"&set "s=!s! !_s:~0,%maxZ%!")
  12. echo,!s:~1!
  13. )
  14. endlocal&pause&exit/b
  15. :_strLen
  16.    set "_str=_!%~1!" &set "_Len=0"
  17.    for %%n in (64 32 16 8 4 2 1) do (
  18.       if "!_str:~%%n,1!" neq "" (set/a "_Len+=%%n"&set "_str=!_str:~%%n!")
  19.    )
  20.    set "%~2=!_Len!" &exit/b
复制代码

特此备注》重写了原代码,改用批处 ‘原装’ 的字符串长度计算方法,再请出制表符 ‘显灵’,似乎消除了以前格式化输出时中英文字符混合字段的占位问题...
1

评分人数

TOP

本帖最后由 aloha20200628 于 2024-7-18 12:25 编辑

回复 11# shenlong

参考12楼的经验,谢谢 重写了9楼代码,用以下1.txt示例文件测试效果明显 楼主可试试...
1.txt》
aa  自x车 1232   米
mm命名  abc 5555  米
bbbbb  密码可靠 66  米
同轴3xx   国产321   456 米

TOP

本帖最后由 aloha20200628 于 2024-7-21 14:08 编辑


关于中英文混合文本行的对齐输出最终取决于显示字体
已知的 ‘英文用一个字节,中文用2个字节’ 是指存储单位,而每个字符被物理显示到屏幕上的 ‘显示宽度’ 还是要看所选字体
选择中英文字符等宽字体可以简化算法步骤(因批处的字符串截取偏移量视同中英文字符偏移量=1),但显示观感会大打折扣
而选择中英文字符显示宽度成等分关系的字体(例如英文字符占1个显示宽度,中文字符占2个显示宽度,而cmd简中窗口的默认字体即为此型字体)须实时获取每个字段的显示宽度与 ‘全文最长字段’ 显示宽度的差距,此差距即所谓 ‘每个字段的空格填充量’,由此确保每行各列不等长字段能够对齐显示,据此原理调整了9楼代码如下,并已在cmd简中窗口中实测多种样本(最长混合字段可自定义,列数可自定义)均予顺利通过...
  1. @echo off &setlocal enabledelayedexpansion &set "maxZ=0"
  2. for /f "delims=" %%a in (1.txt) do for %%s in (%%a) do (
  3. set "s=%%s"&set "_len="&(call :_strLen)
  4. if !_len! gtr !maxZ! set "maxZ=!_len!"
  5. )
  6. for /f "delims=" %%a in (1.txt) do (
  7. set "ss=" &for %%s in (%%a) do (
  8. set "s=%%s"&set "_len="&(call :_strLen)
  9. set/a "z=maxZ-_len"&set "_s="&for /l %%k in (1,1,!z!) do set "_s=!_s! "
  10. set "ss=!ss! %%s!_s!"
  11. )
  12. echo,!ss:~1!
  13. )
  14. endlocal&pause&exit/b
  15. :_strLen //逐个字符计算》中文字符累加2,英文字符累加1。
  16.    if not defined s exit/b
  17.    if "!s:~0,1!" gtr "Z" (set/a "_len+=2") else (set/a "_len+=1")
  18.    set "s=!s:~1!" &goto :_strLen
复制代码

TOP


用7楼获取全文最大字段长度的方法(中英文字符按存储字节数计算长度)可以进一步简化34楼所用计算方法中须区分中英文字符的步骤...
  1. @echo off &setlocal enabledelayedexpansion &set "maxZ=0"
  2. for /f "delims=" %%a in (1.txt) do for %%s in (%%a) do (
  3. set/p="%%s"<nul>"0.0"
  4. for %%b in (0.0) do if %%~zb gtr !maxZ! set "maxZ=%%~zb"
  5. )
  6. for /f "delims=" %%a in (1.txt) do (
  7. set "ss=" &for %%s in (%%a) do (
  8. set/p="%%s"<nul>"0.0" &for %%b in (0.0) do set/a "z=maxZ-%%~zb"
  9. set "_s="&for /l %%k in (1,1,!z!) do set "_s=!_s! "
  10. set "ss=!ss! %%s!_s!"
  11. )
  12. echo,!ss:~1!
  13. )
  14. del/q "0.0"&endlocal&pause&exit/b
复制代码

TOP

本帖最后由 aloha20200628 于 2024-7-21 15:59 编辑

回复 1# shenlong

跑完35层楼,总算能踏踏实实给楼主一个用批处拿下本帖(最长混合字段可自定义,列数可自定义)的解决方案了...

TOP

本帖最后由 aloha20200628 于 2024-7-23 11:19 编辑


若批处字符串里包含转义字符,有如一旦撞上 “台风” 就是 “天灾”,只能尽量减免吧...
更新35楼代码如下,用递归子过程替换 for %%s in (%%a) do ... 以便纠正 ,;= 等其余系统默认分隔符以及*?通配符的影响...
  1. @echo off &setlocal &set "maxZ=0"
  2. for /f "delims=" %%a in (1.txt) do for /f "delims=   " %%b in ("%%a") do (
  3. set "a=%%a"&call :getMaxZ
  4. call set/p=%%maxZ%%<nul>0.0
  5. set/p maxZ=<0.0
  6. )
  7. for /f "delims=" %%a in (1.txt) do for /f "delims=   " %%b in ("%%a") do (set "a=%%a"&set "ss="&call :printAll)
  8. del/q "0.0" 2>nul&endlocal &pause &exit/b
  9. :getMaxZ
  10. for /f "tokens=1* delims=   " %%1 in ("%a%") do (set "a=%%2"&set/p="%%1"<nul>"0.0")
  11. if "%a%"=="" (exit/b) else for %%v in (0.0) do (set "v=%%~zv")
  12. (if %v% gtr %maxZ% set "maxZ=%v%") & goto :getMaxZ
  13. :printAll
  14. for /f "tokens=1* delims=   " %%1 in ("%a%") do (set "s=%%1"&set "a=%%2"&set/p="%%1"<nul>"0.0")
  15. for %%v in (0.0) do (set/a "z=maxZ-%%~zv")
  16. setlocal enabledelayedexpansion &set "_s=" &for /l %%k in (1,1,!z!) do (set "_s=!_s! ")
  17. set "ss=!ss! !s!!_s!" &if "%a%"=="" (set/p="!ss:~1!"<nul&echo,&endlocal&exit/b)
  18. endlocal &set "ss=%ss%" &goto :printAll
复制代码

TOP

本帖最后由 aloha20200628 于 2024-7-23 11:18 编辑

回复 54# ppll2030

更新了50楼代码,滤掉了全空白字符行(仅包含中英文空格+制表符),以免运行中被阻塞...

TOP

本帖最后由 aloha20200628 于 2024-7-23 14:37 编辑

回复 60# ppll2030

我说的过滤掉中英文空格+制表符构成的 ‘全空白行’,其中的中文空格即全角空格。delims表达式指定的这三个字符复制到代码区中有时会 ‘变形’ 不过知道此意你在自己的代码中调整就是了

TOP

返回列表