Board logo

标题: [求助]怎样用bat对齐文本? [打印本页]

作者: wydos     时间: 2006-12-13 07:15    标题: [求助]怎样用bat对齐文本?

文本内容形式是这样的:
新编中医临证备要 作者:卢祥之  SS号:10804820   索书号:R24/15  
中医临床学基础 作者:湖南中医学院  SS号:10806223   索书号:R24/1  
临床证治精论 作者:徐春家 秦群   SS号:10806254   索书号:R24/152  
.
.
.
我想把它按类对齐,变成如下形式:
新编中医临证备要 作者:卢祥之          SS号:10804820   索书号:24/15
中医临床学基础    作者:湖南中医学院   SS号:10806223   索书号:24/1
临床证治精论       作者:徐春家 秦群   SS号:10806254   索书号:24/152
.
.
.
.
.

[ Last edited by wydos on 2006-12-13 at 07:17 AM ]
作者: a9319751     时间: 2006-12-13 07:19
隐隐约约记得哪个能制造TAB跳格
好象是8个空格
作者: namejm     时间: 2006-12-13 07:35
  需要统计每一节字符串的最大长度才好排版。
作者: lxmxn     时间: 2006-12-13 07:53

  不知道WMIC可不可以,问下版主就知道了。

作者: youxi01     时间: 2006-12-13 08:03
个人认为,纯粹的P很难实现,因为P很难判断变量的字节数,所以要借助于vbs。
::On Error Resume Next
echo ' > nul &cls & @echo off
echo ' > nul &for /f "tokens=1,2,3,4 delims= " %%i in (test.txt) do (
echo ' > nul &cscript //E:vbs "%~f0"  "%%i" "%%j" "%%k" "%%l" //nologo)
echo ' > nul &pause>nul

::str0=wscript.arguments(0)
::str1=wscript.arguments(1)
::str2=wscript.arguments(2)
::str3=wscript.arguments(3)
::wscript.echo align(str0)&align(str1)&align(str2)&align(str3)
::function align(obj)
::  length=len(obj)
::  flag=0
::  for i=1 to length
::     str=mid(obj,i,1)
::     str=asc(str)
::     if str<0 then
::         flag=flag+1
::     end if
::   next
::   length=20-length-flag
::   align=obj&space(length)
::end function
说明:将要处理的文字保存为test.txt,本代码保存为:ok.bat

[ Last edited by youxi01 on 2006-12-13 at 08:14 AM ]
作者: electronixtar     时间: 2006-12-13 09:15


  Quote:
不知道WMIC可不可以,问下版主就知道了。

汗,WMIC拿来处理文本~~~
作者: pengfei     时间: 2006-12-13 12:09

@echo off
setlocal enabledelayedexpansion
for /f "tokens=1-4 delims=作者:SS号:索书号:" %%i in (test.txt) do (
    set a=&set b=&set c=
    call :detect %%i
    set /a num=2*10-2*num
    call :add %%i
    set a=!i!
    call :detect %%j
    set /a num=2*8-2*num
    call :spa %%j
    set /a num+=!sp!
    call :add %%j
    set b=!i!
    call :detect %%k
    set /a num=12-num
    call :add %%k
    set c=!i!
    echo !a!作者:!b!SS号:!c!索书号:%%l>>array.txt
)
start array.txt
goto :eof

:detect
set x=%*◎
set num=0
:detect_
if not "%x:~0,1%"=="◎" (
    set /a num+=1
    set "x=%x:~1%"
    goto :detect_
)
goto :eof

:add
set y=%*
for /l %%i in (1,1,%num%) do set y=!y!
set i=%y%
goto :eof

:spa
set z=%*◎
set sp=0
:spa_
if not "%z:~0,1%"=="◎" (
    if "%z:~0,1%"==" " set /a sp+=1
    set "z=%z:~1%"
    goto :spa_
)
goto :eof
只测试了你给的三行, 其他格式和特殊字符没有考虑. 请注意冒号全角和半角的区别.

[ Last edited by pengfei on 2006-12-13 at 12:53 PM ]
作者: zh159     时间: 2006-12-13 14:30
“delims=作者:SS号:索书号:”中有个缺点,只要某个位置有其中一种字符就导致缺失
可以先考虑将“作者:”“SS号:”“索书号:”替换为$后再处理

亮点:检测字节数

  Quote:
>Temp.txt set/p=!Temp_%1!<nul
for %%i in (Temp.txt) do set %1=%%~zi


@echo off
setlocal enabledelayedexpansion
cd.>array.txt
::检测每段最大字节数
for /f "delims=" %%i in (test.txt) do (
    set "Temp$=%%i"
    set "Temp$=!Temp$:作者:=$!"&&set "Temp$=!Temp$:SS号:=$!"&&set "Temp$=!Temp$:索书号:=$!"
  for /f "tokens=1-4 delims=$" %%i in ("!Temp$!") do (
    set "Temp_=%%i"&&call :MaxNum 书名
    set "Temp_=%%j"&&call :MaxNum 作者
    set "Temp_=%%k"&&call :MaxNum SS号
    set "Temp_=%%l"&&call :MaxNum 索书号
))

::加上空格对齐
for /f "delims=" %%i in (test.txt) do (
    set "Temp$=%%i"
    set "Temp$=!Temp$:作者:=$!"&&set "Temp$=!Temp$:SS号:=$!"&&set "Temp$=!Temp$:索书号:=$!"
  for /f "tokens=1-4 delims=$" %%i in ("!Temp$!") do (

    set "Temp_书名=%%i"&&call :Num 书名
  set /a 书名=%Max书名%-!书名!&&call :Add 书名

    set "Temp_作者=%%j"&&call :Num 作者
  set /a 作者=%Max作者%-!作者!&&call :Add 作者

    set "Temp_SS号=%%k"&&call :Num SS号
  set /a SS号=%MaxSS号%-!SS号!&&call :Add SS号

    set "Temp_索书号=%%l"&&call :Num 索书号
  set /a 索书号=%Max索书号%-!索书号!&&call :Add 索书号

>>array.txt echo.!Temp_书名!作者:!Temp_作者!SS号:!Temp_SS号!索书号:!Temp_索书号!
))
del Temp.txt
pause
exit

::检测字节数
:MaxNum
>Temp.txt set/p=%Temp_%<nul
for %%i in (Temp.txt) do if %%~zi GTR !Max%1! set Max%1=%%~zi
goto :eof

::检测字节数
:Num
>Temp.txt set/p=!Temp_%1!<nul
for %%i in (Temp.txt) do set %1=%%~zi
goto :eof

::加空格数量
:Add
if "!%1!" == "0" goto :eof
set "Temp_%1=!Temp_%1! "
set /a %1-=1
goto Add
[ Last edited by zh159 on 2006-12-13 at 09:35 AM ]
作者: HUNRYBECKY     时间: 2006-12-13 21:53
都太棒了,我对FOR语句总是用的不好。想不到FOR语句用处这么大,学习了。
作者: HUNRYBECKY     时间: 2006-12-13 22:14


  Quote:
Originally posted by youxi01 at 2006-12-13 08:03:
个人认为,纯粹的P很难实现,因为P很难判断变量的字节数,所以要借助于vbs。
[code]
::On Error Resume Next
echo ' > nul &cls & @echo off
echo ' > nul & ...

问下,::不是和REM 一样,是注释吗?为什么把他的::后,运行就不正常了.奇怪,楼主能否解释下.
作者: youxi01     时间: 2006-12-14 01:18
因为::在vbs中可以被认识(识别为换行),而rem却不能被vbs认识!
作者: youxi01     时间: 2006-12-14 01:22
7F的问题:要是书名中有E文字符或者数字,怎么解决?
8F用文件的大小来判断字节数,真是高!
作者: qzwqzw     时间: 2006-12-14 01:51
对齐还是先补后拆最省事。
作者: 无奈何     时间: 2006-12-14 02:31
zh159 兄 8 楼用字节数判长确是亮点,CMD 下字串汉字和英文字母长度都是 1 ,用字节判断很好的解决了这个问题。不过 CMD 下特殊字符实在是然人头疼的问题,我也一直没有找到好的方法。
本帖是很典型的格式化输出的问题,大多数语言 pringf 都能很好解决。
可以试试下面的 awk 的脚本:
用法:gawk -f script.awk file.txt
BEGIN{
        FS=" +(作者|[Ss][Ss]号|索书号):"       
}
{
        L1=L1<length($1)?(length($1)):L1
        L2=L2<length($2)?(length($2)):L2
        L3=L3<length($3)?(length($3)):L3
        L4=L4<length($4)?(length($4)):L4
        for (i=1;i<=NF;i++)
                R[NR,i]=$i
}
END{
        format = "%-"L1"s 作者:%-"L2"s SS号:%-"L3"s 索书号:%-"L4"s\n"
        for(i=1;i<=NR;i++)
                if(R[i,1] != "") printf format, R[i,1],R[i,2],R[i,3],R[i,4]
}
gawk 下载:http://www.klabaster.com/progs/gawk32.zip

[ Last edited by 无奈何 on 2006-12-14 at 03:23 AM ]
作者: ccwan     时间: 2006-12-14 02:44
恕我愚钝,兄的代码看不懂。
为防拍马的嫌疑,就不给兄加分了,见谅。
作者: ccwan     时间: 2006-12-14 02:59
求解:
无奈何兄,试过兄的代码,发现显示内容缺少第一行,不知何故?
作者: 无奈何     时间: 2006-12-14 03:23
我这里没有问题啊,少了哪一行?
有点小问题,空行也会输出,修正一下。
作者: ccwan     时间: 2006-12-14 03:31
新代码没有问题了!
请问增加if语句是什么意思?
作者: HUNRYBECKY     时间: 2006-12-14 03:43


  Quote:
Originally posted by youxi01 at 2006-12-14 01:18:
因为::在vbs中可以被认识(识别为换行),而rem却不能被vbs认识!

youxi01兄,我真不知有如此用法,但是我是把你的代码保存在BAT文件而非VBS文件中,我也曾试着保存到VBS中,但无法运行。这又是何故?
作者: HUNRYBECKY     时间: 2006-12-14 04:03


  Quote:
Originally posted by youxi01 at 2006-12-13 08:03:
个人认为,纯粹的P很难实现,因为P很难判断变量的字节数,所以要借助于vbs。
[code]
::On Error Resume Next
echo ' > nul &cls & @echo off
echo ' > nul & ...

能否解释下在BAT中编写VBS脚本并运行的机理,一点都看不懂是怎么执行的,谢谢!
作者: 无奈何     时间: 2006-12-14 04:03


  Quote:
Originally posted by ccwan at 2006-12-14 03:31:
新代码没有问题了!
请问增加if语句是什么意思?

加上这条判断语句后,空行就不会输出了。小问题是空白行(只含有空格的行)还是会输出的,只需将 if(R[i,1] != "") 改为 if(R[i,2] != "") 能解决空白行的问题。
作者: ccwan     时间: 2006-12-14 04:07
谢谢。
看来有必要学学了。
作者: pengfei     时间: 2006-12-14 04:41
zg159兄和无奈何兄的代码精彩, 更通用. 而用文件大小判断字节数是更为省事的方法.

当时分析楼主给的三行代码, 初步得到规律写的代码自然不能计算中文字符的英文字符的字节差别. 也想用文件大小判断, 出于对生成临时文件的敏感, 故只针对1F三行代码做处理.

而除了zh159兄8F用文件大小判断字节数外还有其他方法, 不用生成临时文件. 但效率会很低, 为了扩展思路, 熟悉不同的算法, 大家可以尝试使用下面的算法实现对中文汉字和英文字符的判断.

一、用for列举出要匹配的字符, 一旦匹配成功, num+1。

二、FOR循环执行完毕, 开关如没关闭则判断其为汉字,故num+2。

三、整个嵌套循环执行完毕, 计算num的值进行空格填充。

希望大家能写出更加精彩的代码,用灵活的思路,更先进的算法,弥补P处理脚本功能上的不足,  带动本论坛的发展^_^
作者: youxi01     时间: 2006-12-14 04:42


  Quote:
Originally posted by HUNRYBECKY at 2006-12-14 03:43 AM:


youxi01兄,我真不知有如此用法,但是我是把你的代码保存在BAT文件而非VBS文件中,我也曾试着保存到VBS中,但无法运行。这又是何故?

一定要保存为bat文件,因为它是针对P处理的!
作者: youxi01     时间: 2006-12-14 04:46


  Quote:
Originally posted by HUNRYBECKY at 2006-12-14 04:03 AM:



能否解释下在BAT中编写VBS脚本并运行的机理,一点都看不懂是怎么执行的,谢谢!

在P处理中,会忽略::打头的行(认为是解释语句),而当它作为vbs运行时,却可以被识别;同时,在vbs中,会认为 ' 后面的内容为注释内容......

参看:http://www.cn-dos.net/forum/view ... E8%B4%A7&page=1
作者: vkill     时间: 2006-12-14 05:37
还是awk的效果好觉得
作者: cdswf     时间: 2008-5-13 11:10


  Quote:
Originally posted by youxi01 at 2006-12-13 08:03 AM:
个人认为,纯粹的P很难实现,因为P很难判断变量的字节数,所以要借助于vbs。
[code]
::On Error Resume Next
echo ' > nul &cls & @echo off
echo ' > nul & ...

上面的例子是4列,如果是5列、6列怎样写?
最后怎样输出到文档?
我是菜鸟!谢谢!
作者: cdswf     时间: 2008-5-21 10:23
ding!顶到出答案为止!!
作者: bat-zw     时间: 2008-5-21 10:48    标题: 答案:

因论坛处理不了TAB,请运行前将!str!后面的空格改为TAB。
@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%i in (a.txt) do (
    for %%a in (%%i) do call set str=!str!        %%a
    echo !str:~1!&set str=
)
pause>nul

作者: 26933062     时间: 2008-5-21 11:46    标题: 29 楼

zw19750516 兄想简单了。
先测试以下代码
@echo off
echo aaaaaaa        bbbbbbbbb
echo aaaaaaaa        bbbbbbbbb
echo aaaaaaaaaaaaaaaaa        bbbbbbbbb
pause

更何况是中英文混合的。。。。。。。。。。
作者: knoppix7     时间: 2008-5-21 18:28
直接用TAB就可以了...