返回列表 发帖
本帖最后由 buyiyang 于 2024-7-20 21:55 编辑

回复 25# ppll2030

这个不限列数,还用了两种方法算字符宽度。
@echo off
chcp 437 >nul
set "Separator=@"
set "inputfile=a.txt"
setlocal enabledelayedexpansion
:loop
set /a column+=1
set /a #C%column%max=mark=0
for /f "tokens=%column%" %%i in (%inputfile%) do (
    call :strlen "%%i"
    if !len! geq !#C%column%max! set /a #C%column%max=len
    set mark=1
    )
if %mark% equ 1 goto :loop
set /a column-=1
chcp 936 >nul
set /a lines=0
(for /l %%i in (1,1,%column%) do call :output %%i)>$.temp
set "Separator="&set arg=" delims=%Separator%" "rem"
set "inputfile=$.temp"&(for /l %%i in (1,1,%lines%) do call :output %%i %arg%)>output_%inputfile%
del /q $ $.temp
pause&exit
:strlen
set "str=_%~1"
set "len=0"
for %%n in (64 32 16 8 4 2 1) do (
    if "!str:~%%n,1!" neq "" (
        set/a "len+=%%n"
        set "str=!str:~%%n!"
        )
)
exit /b
:output
if %1 equ 1 goto :output_2
for /f "tokens=1,%1%~2" %%a in (%inputfile%) do (
    if "%%b"=="" (set "field=-") else set "field=%%b"
    %~3 set/p="!field!"<nul>$&for %%i in ($) do (set len=%%~zi)
    %~3 set /a spaceNum=!#C%1max!-len+2,n+=1
    set "outstr=!outstr!%Separator%!field!"
    %~3 for /l %%i in (1,1,!spaceNum!) do set "outstr=!outstr! "
    )
%~3 if %n% geq %lines% set /a lines=n
%~3 set /a n=0
echo,!outstr!
set "outstr="
exit /b
:output_2
for /f "tokens=%1%~2" %%a in (%inputfile%) do (
    if "%%a"=="" (set "field=-") else set "field=%%a"
    %~3 set/p="!field!"<nul>$&for %%i in ($) do (set len=%%~zi)
    %~3 set /a spaceNum=!#C%1max!-len+2,n+=1
    set "outstr=!outstr!%Separator%!field!"
    %~3 for /l %%i in (1,1,!spaceNum!) do set "outstr=!outstr! "
    )
%~3 if %n% geq %lines% set /a lines=n
%~3 set /a n=0
echo,!outstr!
set "outstr="COPY

TOP

本帖最后由 ppll2030 于 2024-7-20 23:37 编辑

回复 31# buyiyang


    厉害了。大佬这个应该是完美通用版了。

TOP

本帖最后由 newswan 于 2024-7-21 15:54 编辑

回复 29# 娜美

前面发的都没计算全角字符
#36 #37  计算了全角,用 ":" 分隔字段

TOP

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


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

TOP


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

TOP

本帖最后由 newswan 于 2024-7-21 20:35 编辑

支持全角字符
awk -f format-table.awk data.txt
function getWidth(str,LenStr,LenASC,LenHZ) {
LenStr = length(str)
LenASC = gsub( /[\x00-\x7F]/ , "" , str )
LenHZ = length(str) / length("一")
return  LenASC + LenHZ * 2
}
function getLengthHZ(str,LenHZ) {
gsub( /[\x00-\x7F]/ , "" , str )
LenHZ = length(str) / length("一")
return  LenHZ
}
BEGIN {
FS = " "
while ( getline < ARGV[1] ) {
for (i = 1; i <= NF; i++) {
len = getWidth($i)
if ( len > maxWidth[i] ) {
maxWidth[i] = len
}
}
}
# print "--maxWidth--"
# for ( i in maxWidth ) {
# printf "%4s" , maxWidth[i]
# }
# printf "\r\n"
# print "----"
}
{
for (i = 1; i <= NF; i++) {
LenHZ = getLengthHZ($i)
printf "%-*s:" , maxWidth[i] + LenHZ , $i
}
printf "\r\n"
}COPY
注意 第 35 行 由于 awk 环境不同,可能是 "+ LenHZ" 可能是 "- LenHZ"

TOP

本帖最后由 newswan 于 2024-7-21 19:56 编辑

支持全角字符
format-table.ps1 "in.txt" "out.txt"
param(
[String]$filenameIn ,
[String]$filenameOut
)
$file = Get-Content -Path $filenameIn -Encoding UTF8
$maxWidth = @{}
$file | ForEach-Object {
$arr = $_  -split "\s+"
for ( $i = 0 ; $i -lt $arr.count ; $i++ ){
$Width = ($arr[$i]).length + ( $arr[$i] -replace "[\x00-\x7F]","" ).length
if ( $maxWidth[$i] -lt $Width ) {
$maxWidth[$i] = $Width
}
}
}
$strTable = [System.Collections.ArrayList]@()
$file | ForEach-Object {
$arr = $_  -split "\s+"
$str = ""
for ( $i = 0 ; $i -lt $arr.count ; $i++ ){
$LenHZ = ( $arr[$i] -replace "[\x00-\x7F]","" ).length
$str += ($arr[$i]).PadRight( $maxWidth[$i] - $LenHZ , " " ) + ":"
}
[void]$strTable.add( $str ) #$str -replace "\s$",""
}
$strTable | Out-File -Encoding 'UTF8' -FilePath $filenameOutCOPY

TOP

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

回复 1# shenlong

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

TOP

回复 38# aloha20200628

多谢,这次真学到了。

TOP

回复 36# newswan


    第35行应该是maxWidth - LenHZ

TOP

回复 35# aloha20200628


    使用这段代码如果字段中有=,等批处理分隔符的话会被错误分割;而且以“全文最大字段长度”为标准,当原文件字段长度差距悬殊时会使结果中字符较少的列视觉间隔过大而不协调。

TOP

本帖最后由 娜美 于 2024-7-21 17:40 编辑

我带着好奇心, 跟着这个贴题测过上面你们所说的解决方案,  都没有通过以下文本测试,   有的虽然解决了在cmd屏幕里对齐,  但输出到文本又是另一个不对齐现象发生了
测试要对齐文本 a.txt
aa          1232    米
bbbbb     66       米
b 66  米
cccccccccccccccccccccccccccccccccccc    c   cccccccccccccccccccccccccccccc  cc   c          米 c
c cc    ccc     v          米
补补补补补补补补补补补补补补补补补  cccccccccccccccccccccccccccccc          补补补补补补补补补补补补补补补补补       c       c                 c
补  c                      cccccccccccccccccccccccccccccc    c             c                cCOPY
Out.txt  请复制到txt文本中观看才能看到对齐大概样式
对齐后, 输出到文本中它们大概至少应该是这样的吧,  但是都相差甚远呢,  到目前为止还没有解决输出到文本对齐问题
aa                                                          1232                                                   米
bbbbb                                                    66                                                      米
b                                                            66                                                      米
cccccccccccccccccccccccccccccccccccc    c                                                        cccccccccccccccccccccccccccccc             cc            c                米 c
c                                                            cc                                                       ccc                                                        v             米
补补补补补补补补补补补补补补补补补       cccccccccccccccccccccccccccccc          补补补补补补补补补补补补补补补补补       c             c                 c
补                                                          c                                                         cccccccccccccccccccccccccccccc             c             c                 cCOPY

TOP

有的虽然解决了在cmd屏幕里对齐,  但输出到文本但输出到文本又是另一个不对齐现象发生了
娜美 发表于 2024-7-21 17:30

先看看我20楼和30楼说的字体问题……

TOP

回复 40# buyiyang


对,由于 awk 使用环境不同,有的地方是 + 有的地方是 -

TOP

本帖最后由 newswan 于 2024-7-21 20:05 编辑

回复 42# 娜美

#36 #37 输出正确
输出到屏幕正确,保存到文件也应该正确,文件不能对齐,是因为编辑器的字体问题

TOP

返回列表