中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --
联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟
中国DOS联盟论坛
现在时间是 2026-10-01 21:16
共 47,813 主题排行 / 349,918 发帖 / 今日 0 篇 / 48,279 会员排行
DOS批处理 & 脚本技术(批处理室) » 统计文本文件的字符个数
可打印版本  4,220 / 31
第1楼 pusofalse 发表于 2008-04-24 21:59
银牌会员 发帖 646 积分 1,604
统计文本文件的字符个数
@echo off&setlocal enabledelayedexpansion
set/a n=0,m=0,z=0,x=0
if not "%1"=="" (set file=%1) else set /p file=把要统计的文件拖到此处:
if not exist %file% echo 找不到文件&exit/b
echo 正在计算,请稍候。。。
for /f "tokens=*" %%a in ('findstr /n .* %file%') do (
set str=%%a
set str=!str:*:=!
call :lp
)
set /a n=%n%+%x%+%z%
echo %file%中有%n%个字符,[Space]有%m%个。
pause&goto :eof


:lp
if defined str (
set var=!str:~0,1!
if not "!var!"=="" set /a n+=1
if "!var!"=="!" set /a z+=1
if "!var!"=="^^" set /a x+=1
if "!var!"==" " set /a m+=1
set str=!str:~1!
goto lp
)

虽然对特殊字符稍微做了一点处理,但同样不适用于P。。。
第2楼 slore 发表于 2008-04-24 22:28
铂金会员 发帖 2,478 积分 5,212
VBS的len函数很好用嗬。
第3楼 slore 发表于 2008-04-24 22:28
铂金会员 发帖 2,478 积分 5,212
如果纯e文的话,直接看大小嗬。
第4楼 bat-zw 发表于 2008-04-24 22:42
金牌会员 发帖 1,276 积分 3,105
这种学习方法值得提倡:
别的不说,楼主举一返三的精神是可贵的,也是一条提高的捷径,加油!!!
第5楼 pusofalse 发表于 2008-04-24 23:19
银牌会员 发帖 646 积分 1,604
谢谢楼上几位。。。VBS不会用。。。只会用一个msgbox - -|||
第6楼 bat-zw 发表于 2008-04-25 01:27
金牌会员 发帖 1,276 积分 3,105
为支持楼主也来一个:
特殊字符太难处理了,故没考虑:


[ Last edited by zw19750516 on 2008-4-25 at 01:37 AM ]
第7楼 pusofalse 发表于 2008-04-25 02:31
银牌会员 发帖 646 积分 1,604
Originally posted by zw19750516 at 2008-4-25 01:27 AM:
特殊字符太难处理了,故没考虑:
第8楼 bjsh 发表于 2008-04-25 14:19
银牌会员 发帖 621 积分 2,000
这一段倒是 不怕特殊字符。。 它是打印出每一行的字符数, 并没有进行
整体统计。。


当然你也可以用下面这个进行 整体统计,
但是这个对稍大点的文件就会有问题。。
导致setlocal 递归层过大。。


这里有命令行固有的缺陷

假如你想完完整整的(包括特殊字符)获取到, 那在set "var=%%a"
之前 一定不要打开 变量延迟, 不然!号和^会被吃掉。。

但这样也造成另一个问题:

假如这有最开始的一个环境变量表
|----------------------------------------------|
| |
| |
| |
-------------------------------------------------

执行set "var=%%a"后变为:
假如var=1:abcd
|----------------------------------------------|
| |
| var=1:abcd |
| |
-------------------------------------------------

当你执行 setlocal 时, 会产生一个新表, 实际上是copy调用setlocal的那张表,
但是以后对环境变量的修改只会作用于新表,当执行 endlocal 时,会恢复到原来
那张表。

执行setlocal 后产生新表
|----------------------------------------------|
| |
| var=1:abcd |
| |
-------------------------------------------------
执行
set var=!var:*:=!
call :Loop
后这张新表变为:
|----------------------------------------------|
| |
| var=abcd |
| n=4 |
-------------------------------------------------

当执行endlocal时 环境变量的表 恢复到最初 即

|----------------------------------------------|
| |
| var=1:abcd |
| |
-------------------------------------------------

可见 n 没有了。。
这也是为什么第一个代码 只统计每一行 而没有 统计全部的原因

因为每一次统计 时 执行 set /a n+=1
n的初始值都为零。

可能有人会有这样的疑问: 不执行endlocal行不行。。
答案是也行, 就比如第二段代码

但是要记住: 一定要在 set "var=%%a"之前关闭掉 变量延迟

这样会不断的递归产生 环境表。

对于小文件还尚可。。 文件行数稍大便会 导致setlocal递归层数过大


所谓cmd固有缺陷:

cmd中实际上没有真正变量的概念
而是以环境变量来模拟或者说是代替的

对于这种方式有个问题
因为 父shell 可以传递环境变量 给子shell
而 子shell 无法 改变父 shell中的环境变量

所以在setlocal后对原“变量”的修改 无法传递回来。。

除非 将其存入磁盘。。

================================

所以 更可行的方式 是 利用第一个代码, 将各行的字符数写入临时文件

最后再从 临时文件中 读取并计算和。。。

缺点自然就是 产生临时文件。

======================================
受10楼兄弟的启发, 下面这个代码即可统计 不必产生临时文件,
而且也 发现了 把变量传递回来的好办法。 很聪明的一个办法。。。



主要在两点。。
1) 让 set /a total+=n 脱离 循环的区域 但又被执行到
原因是为了避免 在for中 没执行前的命令行扫描 即将 n 替换掉
2)endlocal&&set /a total+=n
很聪明的做法 也是传递回来的根本原因所在
因为在一行。。。 所以 命令行 会对整体进行扫描
因为扫描时还没有执行endlocal, n 的值仍然存在, 而对其的替换恰发生在此时
扫描完毕后 真正执行时,endlocal 后 还原回原来的环境变量表, 但是
set /a total+=n 在扫描后 n 被替换为一个确定的值, 因此n的值通过total
被传递回原来的环境表量表

刚好利用了 扫描替换变量和执行的时间差。。

注意一定要在同一行,
endlocal
set /a total+=n
分开写, 第二行则永远是零了。。。


[ Last edited by bjsh on 2008-4-26 at 11:26 AM ]
第9楼 plp626 发表于 2008-04-25 14:38
银牌会员 发帖 1,020 积分 2,278
要想函数用的好,setlocal 必须掌握!
第10楼 26933062 发表于 2008-04-25 18:05
银牌会员 发帖 879 积分 2,268
8 楼版主的代码稍作修改即可达到效果:


[ Last edited by 26933062 on 2008-4-25 at 06:06 PM ]
第11楼 bat-zw 发表于 2008-04-25 21:41
金牌会员 发帖 1,276 积分 3,105
顶!!!
bjsh版主描述的太清楚了,确实特殊字符太难处理了,尤其是在字符截取和开启变量延迟时,这里还真是cmd的瓶颈啊。
第12楼 bat-zw 发表于 2008-04-25 21:44
金牌会员 发帖 1,276 积分 3,105
Originally posted by 26933062 at 2008-4-25 18:05:
8 楼版主的代码稍作修改即可达到效果:
第13楼 pusofalse 发表于 2008-04-25 21:55
银牌会员 发帖 646 积分 1,604
以下代码转自lxmxn
@echo off&setlocal enabledelayedexpansion
set /p file=
for /f "delims=: tokens=1*" %%a in ('findstr /n .* %file%') do (
set n=&set str=%%b
if not "!str!"=="" (
for %%i in (!str!) do set /a n+=1
echo/line:%%a !n!个字符串。。。【!str!】
) else (
echo/line:%%a 0个字符串。。。
)
)
pause>nul&cls&goto :eof

只要有特殊字符,字符串个数也会计算错误,难道没有好的方法了吗~
第14楼 bat-zw 发表于 2008-04-25 21:58
金牌会员 发帖 1,276 积分 3,105
暂时想不到啊,其实我一直在思考这个问题,也一直找不到好的解决方案。
第15楼 bjsh 发表于 2008-04-25 22:06
银牌会员 发帖 621 积分 2,000
10 楼的代码很聪明 真的很聪明!
1 2 3  下一页
[ 联系联盟系统管理团队 - 中国DOS联盟 - 标准版 ]
Sponsored by ifanr Inc | © 2001–2023