Board logo

标题: [文本处理] 如何移动指定的某列数据到最后、合计指定列的数据 [打印本页]

作者: youaoyi    时间: 2008-9-2 17:00     标题: 如何移动指定的某列数据到最后、合计指定列的数据

在经过群中珊瑚海朋友指点后,  琢磨着将批处理做成以下这个样子,
由于自己不懂如何将变量"%wjmc%"写入到for语句中才能正常有效,
只好使用了复制来复制去的笨方法,各位见笑了。

@echo off
cls
mode con cols=40 lines=16 &color 0B
title 指定文本列置于每行最后一列
cls
echo.
echo.
echo 请把要处理的TXT文本文件拖到本窗口
set wjmc=:
echo.
set /p wjmc=  待处理的文件为:
set "wjmc=%wjmc:"=%"
echo.
echo.
::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal enabledelayedexpansion
copy "%wjmc%" c:\temp_hh.txt
for /f "tokens=1,2,3,4,5,6,7,8 delims=|" %%a in (c:\temp_hh.txt) do echo %%a-%%b-%%c-%%d-%%e-%%g-%%h-%%f >>c:\temp_hh2.txt
for /f "delims=" %%m in (c:\temp_hh2.txt) do (
set var=%%m
set "var=!var:-=|!"
echo !var! >>c:\temp_hh3.txt
)
move /Y c:\temp_hh3.txt "%wjmc%"_换列.txt
pause
del c:\temp_hh.txt>nul2>nul
del c:\temp_hh2.txt>nul2>nul
echo 结束
pause


目的就是可以把一个文本中的某一列数据移动到各行的最后.

对于下面这个样本, 这个批处理是可以完成的(执行后"需要移动到最后的字段"被放到了文本的最后).

1|200757|单方合同|其它|殷顺|45665需要移动到最后的字段|4000.0|
2|200752|合同|经济原因|宝举|3454534534需要移动到最后的字段|10232.35|
3|202810|合同|经济原因|传龙|56546需要移动到最后的字段|479.0|
4|202810|单方合同|经济原因|传龙|2222需要移动到最后的字段|479.0|
5|202810|合同|其它原因|传龙|4343需要移动到最后的字段|23.72|
6|202810|合同|经济原因|传龙|5454667需要移动到最后的字段|23.72|


问题是手头上有几百个类似的文本, 各行数据的列数并不一定是7组,
因此想要移动的数据也不一定在第6列,比如下面的样本2、样本3,

样本2:
1|200757|单方合同|其它|殷顺|45665需要移动到最后的字段|4000.0|其它|殷顺|200757|单方合同
2|200752|合同|经济原因|宝举|3454534534需要移动到最后的字段|10232.35|其它|殷顺|200757|单方合同
3|202810|合同|经济原因|传龙|56546需要移动到最后的字段|479.0|其它|殷顺|200757|单方合同
4|202810|单方合同|经济原因|传龙|2222需要移动到最后的字段|479.0|其它|殷顺|200757|单方合同
5|202810|合同|其它原因|传龙|4343需要移动到最后的字段|23.72|其它|殷顺|200757|单方合同
6|202810|合同|经济原因|传龙|5454667需要移动到最后的字段|23.72|其它|殷顺|200757|单方合同


样本3:
1|200757|45665需要移动到最后的字段|4000.0|其它|殷顺|200757|单方合同
2|200752|3454534534需要移动到最后的字段|10232.35|其它|殷顺|200757|单方合同
3|202810|56546需要移动到最后的字段|479.0|其它|殷顺|200757|单方合同
4|202810|2222需要移动到最后的字段|479.0|其它|殷顺|200757|单方合同
5|202810|4343需要移动到最后的字段|23.72|其它|殷顺|200757|单方合同


如何才能将上述批处理修改成可以由用户指定想要移动的列, 实现通用呢?

请予以指点。

2008年9月4日追加问题:(仍是上述三个样本)  

如果不移动指定列的话,能否将指定列的数值累加求得合计数?

需要合计的数值在不同文本中处在不同的列,

因此仍需要允许用户任意指定想要求和的数据在哪一列中,

比如样本1,需要求和的数值在最后一列;样本2,需要求和的数值在在第7列;  样本3,需要求和的数值在第4列.....等等

这个问题需要运行速度比较快才行,是不是借用第三方工具并不重要。

[ 本帖最后由 youaoyi 于 2008-9-4 22:22 编辑 ]
作者: youaoyi    时间: 2008-9-2 17:17

还有就是每个文本中的数据量很大,
需要稍微追求一点执行效率,不知道类似SED这样的第三方命令能否做到,
因为之前在本坛请教的一个问题,用SED命令执行速度超快,
可对于一楼的这个问题,我是怎么也想不明白应该怎么写了。

自己弄的这个复制、删除、再复制、再删除的笨方法,自己都受不了,怎么才能将这个"%wjmc%"代入到for公式中去呢?

[ 本帖最后由 youaoyi 于 2008-9-2 17:35 编辑 ]
作者: batman    时间: 2008-9-2 17:39

  1. @echo off&setlocal enabledelayedexpansion
  2. set /p file=请将要处理的文本拖放到这里:
  3. echo.&set /p lie=请输入要处理的列数:
  4. cls&echo.
  5. for /f "usebackq delims=" %%a in ("%file%") do (
  6.      set "str=%%a"&set "str=!str:|= !"&set "n=0"
  7.      for %%i in (!str!) do (
  8.            set /a n+=1
  9.            if !n! equ %lie% (
  10.                    set "var=%%i"
  11.                    ) else (
  12.                    set /p=%%i^|<nul
  13.           )
  14.      )
  15.      set /p=!var!<nul&echo.
  16. )
  17. pause>nul
复制代码

作者: pusofalse    时间: 2008-9-2 18:11

如果你是把文件直接拖到CMD窗口,那么BATMAN版主的代码有点小错误,

for /f "usebackq delims=" %%a in ("%file%") do ....
应该把()中的""去掉。
作者: youaoyi    时间: 2008-9-2 18:30

谢谢 batman 斑竹、pusofalse 斑竹以及群中诸位兄弟的帮忙,

目前对小容量样本的测试完全没有问题,

明日换个大个头的文本 ,测试后再来汇报结果,

谢谢各位了.

[ 本帖最后由 youaoyi 于 2008-9-2 18:32 编辑 ]
作者: terse    时间: 2008-9-2 21:26

  1. @echo off&setlocal enabledelayedexpansion
  2. set/p m=输入列:
  3. for /f "tokens=%m% delims=|" %%i in (a.txt) do call:lp "%%i"
  4. pause&goto :eof
  5. :lp
  6. for /f "%skip% tokens=* delims=|" %%i in (a.txt) do (
  7.     set str=%%i
  8.     set str=!str:%~1^|=!
  9.     set/a n+=1&set skip=skip=!n!
  10.     echo !str!^|%~1&goto :eof
  11. )
复制代码

作者: youaoyi    时间: 2008-9-3 15:45

汇报:  测试了一个300多兆的文本

没等到结束, 运行了半个小时 ctrl _c 退出了

看了下已处理的文档,大约处理了50兆、60万条数据。

速度尚可,但处理一个文档还是要超过三个小时,

如有高人还能加速,望不吝赐教。

六楼的批处理运行时报告内存不足,无法运行。

再次谢谢大家了。

[ 本帖最后由 youaoyi 于 2008-9-3 16:13 编辑 ]
作者: pusofalse    时间: 2008-9-3 16:02

借助第三方工具吧,300M的文本,用纯批不管怎样写,效率总是提不上去。请教论坛的高人吧。
作者: Batcher    时间: 2008-9-3 16:51     标题: 回复 6楼 的帖子

如果要移动的列中包含特殊字符,用set替换的时候会出问题吧?
作者: youaoyi    时间: 2008-9-3 17:31

要移动的列   全部为两个"|"之间的纯数字,
是用来表示金额的.

[ 本帖最后由 youaoyi 于 2008-9-3 17:34 编辑 ]
作者: namejm    时间: 2008-9-3 17:37

  问题的关键是:"把一个文本中的某一列数据移动到各行的最后",这个某一列究竟有什么规律?如果只是举例,而不用文字描述的话,别人是没法了解其中的规律的。如果你不把关键的条件告诉别人,别人写出来的代码总是满足不了你的需求,更谈不上通用。
作者: youaoyi    时间: 2008-9-4 08:45     标题: 回复 11楼 的帖子

正是因为待移动的一列没有什么规律才非常棘手,

因为有非常多的TXT文本, 待移动的数据都位于不同的列。

(不过同一个TXT文本,待移动的数据都是在相同的一列中);

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

只能象三楼batman斑竹那样让用户自行输入数字来指定待移动的数据位于第几列.

------------->  :: echo.&set /p lie=请输入要处理的列数:

三楼的批处理已经能够完美完成所需工作, 只是在处理巨大文本时速度有些慢了。

[ 本帖最后由 youaoyi 于 2008-9-4 08:49 编辑 ]
作者: 随风    时间: 2008-9-4 19:47

第三放工具 sed 应该可以解决效率问题。
论坛第三放工具中有下载的。
具体代码,发帖求助,我在网吧,没有sed ,不能测试。。。
作者: youaoyi    时间: 2008-9-4 22:23

2008年9月4日追加问题:(仍是一楼的三个样本)  

如果不移动指定列的话,能否将指定列的数值累加求得合计数?
需要合计的数值在不同文本中处在不同的列,
因此仍需要允许用户任意指定想要求和的数据在哪一列中,

比如样本1,需要求和的数值在最后一列;样本2,需要求和的数值在在第7列;  
样本3,需要求和的数值在第4列...........等等

这个问题需要运行速度比较快才行,是不是借用第三方工具并不重要。
作者: Batcher    时间: 2008-9-4 22:34

数据列累加问题很容易实现。
如果用批处理,要考虑批处理能够计算的极值。
如果允许用第三方工具,根据CU前人讨论的结果,gawk应该是最快的。
作者: youaoyi    时间: 2008-9-4 23:35

http://chinalinuxpub.com/doc/pro/gawk.html  这里介绍的这个 gawk 吗?

看了半天,没有理出一点头绪,甚至连举例中的语句都没有执行成功.....惨遭失败.....

在这里下载的 gawk        http://www.klabaster.com/progs/gawk32.zip

[ 本帖最后由 youaoyi 于 2008-9-4 23:38 编辑 ]




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