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

[文本处理] 批处理如何实现将多个文本中指定列的数字的小数位数修改成指定位数

本帖最后由 pcl_test 于 2016-11-18 18:06 编辑

多个文本 有多行类似数据
1999/01/04;5.29;5.30;5.17;5.18;1070500;15710576.000
1999/01/05;5.16;5.20;5.10;5.16;1740800;25148052.000
1999/01/06;5.16;5.26;5.15;5.19;1203600;17579928.000
1999/01/07;5.18;5.42;5.17;5.30;1702800;25376532.000
.
.
.
数据来源

需要改成
1999/01/04;5.290;5.300;5.170;5.180;1070500.00;15710576.00
1999/01/05;5.160;5.200;5.100;5.160;1740800.00;25148052.00
1999/01/06;5.160;5.260;5.150;5.190;1203600.00;17579928.00
1999/01/07;5.180;5.420;5.170;5.300;1702800.00;25376532.00
.
.
.


即第2个到第5个分号前面的小数增加成三位,最后两组数字保留小数2位
最后删除最后一行(数据来源)
研究了半天的正则表达替换 在批处理文本工具上可以实现 但是不会在 批处理上实现 请各位老师不吝赐教 特别是多个类似文件的批处理在win7下怎么实现 谢谢
;([0-9]+\...;[0-9]+\...;[0-9]+\...;[0-9]+;[0-9]+\....)$  替换为0;\1
;([0-9]+\...;[0-9]+\...;[0-9]+;[0-9]+\....)$  替换为0;\1
;([0-9]+\...;[0-9]+;[0-9]+\....)$  替换为0;\1
;([0-9]+;[0-9]+\....)$  替换为0;\1
;([0-9]+\....)$  替换为\.00;\1
(\...).$  替换为\1
数据来源   替换为

?啥意思呢?
脚本是写给人看的,是写给用户看的,而不是写给机子看的
用户能看懂、会修改的脚本,才是好脚本。
写易懂的powershell脚本帮人解决问题,进而让用户学会自渔,吾所愿也

TOP

回复 14# PowerShell
好 发在这里
测试 “http://pan.baidu.com/s/1kTIBpMR” 顶楼提供数据 5分钟以内完成 可能机器配置的关系
  1. @if (0)==(0) echo off
  2. for /f "delims=" %%i in ('dir /a-d/b *.txt') do cscript //nologo //E:JScript "%~f0" <"%%i">#&move# "%%i" >nul
  3. pause&exit
  4. @end;
  5. String.prototype.strreg = function() {
  6.    return this.replace
  7.       (/(.+?;)(\d+|\d+(\.\d+));(\d+|\d+(\.\d+));(\d+|\d+(\.\d+));(\d+|\d+(\.\d+));(\d+|\d+(\.\d+));(\d+|\d+(\.\d+))$/gm,
  8.        function(a,b,c,d,e,f,g,h,j,k,l,m,n) {
  9.            return b + (Math.floor(c*100)/100).toFixed(3) + ";" + (Math.floor(e*100)/100).toFixed(3) + ";" + (Math.floor(g*100)/100).toFixed(3) + ";" + (Math.floor(j*100)/100).toFixed(3) + ";" + (Math.floor(l*100)/100).toFixed(2) + ";" + (Math.floor(n*100)/100).toFixed(2);
  10.    });
  11. };
  12. WScript.echo(WScript.StdIn.ReadAll().strreg())
复制代码

TOP

我写的脚本=36分钟完活。
多进程=13分钟
8楼的sed=1小时11分钟,结果对没对还没比对。而且是我运行了n遍我的脚本,都缓存内存的情况下。
抽空重新启动机子,重新复制了源数据,然后进入源目录,type *.txt,让内存缓存,重测试,结果为1小时12分钟。


我的sed版本信息:
sed.exe (GNU sed) 4.2.2
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
and Paolo Bonzini.
GNU sed home page: <http://www.gnu.org/software/sed/>.
General help using GNU software: <http://www.gnu.org/gethelp/>.
E-mail bug reports to: <[email]bug-sed@gnu.org[/email]>.
Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.


sed只是更改源文件,并没生成新文件,当然这问题不大。另外我发现sed在目标目录生成只读随机文件,然后又删除了。

既然有数据,那么就好办,以事实为依据即可。
欢迎大家测测 8楼5分钟的sed和我的脚本。并给出这三套脚本的结果。
脚本是写给人看的,是写给用户看的,而不是写给机子看的
用户能看懂、会修改的脚本,才是好脚本。
写易懂的powershell脚本帮人解决问题,进而让用户学会自渔,吾所愿也

TOP

脚本是写给人看的,是写给用户看的,而不是写给机子看的
用户能看懂、会修改的脚本,才是好脚本。
写易懂的powershell脚本帮人解决问题,进而让用户学会自渔,吾所愿也

TOP

本帖最后由 CrLf 于 2014-6-12 04:45 编辑

感觉用 printf 更方便:
  1. set "rnd=%random%"
  2. del *.$%rnd%
  3. gawk -F";" "{printf(\"%%s;%%s0;%%s0;%%s0;%%s0;%%.2f;%%.2f\",$1,$2,$3,$4,$5,$6,$7)>FILENAME \".$%rnd%\"}" *.txt
  4. del *.txt
  5. ren *.$%rnd% *.
复制代码
学过 c 的用 printf 应该都很爽吧?
实测 800M 文件一秒一个,现在是用类似 sed 的办法输出到临时文件再替换源文件,要实现直接输出到源文件也行,但麻烦点就不写了
----------------------------------------------------------------------------------
9 楼 sed 代码似可简化,不需要那么多正则:
  1. sed -i "s/\...;/&0;/g;s/;/.00;/6;s/.$//" *.txt
复制代码
但用这里无论是用 sed 正则还是面对对象语言都太浪费 cpu 了,貌似 gawk 比较经济适用

TOP

回复 11# PowerShell


    感谢版主关心!EXCEL的宏也试过 速度也慢 估计是自己vba编写方式错误 采用一个文本一个文本导入 宏处理后还要写成一个文件 也没有SED快!
我这个就是股票的数据转换:通达信导出的文本转换为飞狐能用的格式。没有修改过的文本在这里
http://pan.baidu.com/s/1kTIBpMR
经过SED处理后的在这里
http://pan.baidu.com/s/1mgyq2u8

TOP

4000多个文件每个文件5000多行----这样的文件压缩后不算大,能压缩上传网盘么?我想来跑我脚本试试。
众位也可以跑跑自己的脚本看看慢在哪?

另外我补充一下,
你这案例文件不算多,文件行数只能算太小。
你这个如果用 excel+宏 也应该很快完成。
excel有导入文本,然后按【分号】分列,然后就是处理单元格格式了。
这种方法的好处是:不用总去找脚本高人,自己这个低人点两下鼠标也能成功!  
脚本是写给人看的,是写给用户看的,而不是写给机子看的
用户能看懂、会修改的脚本,才是好脚本。
写易懂的powershell脚本帮人解决问题,进而让用户学会自渔,吾所愿也

TOP

回复 9# DAIC


    感谢提醒纠正

TOP

  1. sed -i "s/;/0;/2;s/;/0;/3;s/;/0;/4;s/;/0;/5;s/;/.00;/6;s/[0-9]$//;$d" *.txt
复制代码

TOP

回复 7# terse


     折腾了一天向楼上的老师们学了许多东西 感谢老师!
4000多个文件每个文件5000多行 执行优化后的批处理 看着屏幕1秒钟移动一个文件 算下来要1个多小时  没有办法只能学sed的替换
sed -e  "s/;/0;/2;s/;/0;/3;s/;/0;/4;s/;/0;/5;s/;/.00;/6;s/[0-9]$//g;$d " -i *.txt
5分钟不到完成。唉,毕竟人家SED是专业处理文本的东西。

TOP

回复 6# 观心
这样效率高点不
  1.     @echo off & setlocal enabledelayedexpansion
  2. for /f "delims=" %%f in ('dir /a-d/b *.txt') do (
  3.     set "str="
  4.     (for /f "usebackqtokens=1-5*delims=;" %%a in ("%%f") do (
  5.          if defined str (
  6.             for %%i in (!str1!) do (
  7.                 for /f "tokens=1*delims=." %%j in ("%%i") do (
  8.                     set "s=%%k000"
  9.                     set "s=%%j.!s:~,3!"
  10.                 )
  11.                     set "str=!str!;!s!"
  12.             )
  13.             for %%i in (!str2!) do (
  14.                 for /f "tokens=1*delims=." %%j in ("%%i") do (
  15.                     set "s=%%k00"
  16.                     set "s=%%j.!s:~,2!"
  17.                 )
  18.                     set "str=!str!;!s!"
  19.             )
  20.                     echo !str!
  21.          )
  22.                     set str=%%a&set str1=%%b;%%c;%%d;%%e&set "str2=%%f"
  23.     ))>"%temp%\$"
  24.     move "%temp%\$" "%%f"
  25. )
  26. pause
复制代码

TOP

本帖最后由 观心 于 2014-6-7 22:38 编辑

折腾了半天把删除最后一行加上了 但是感觉应该可以优化一下   处理5个文件每个文件有5000行左右速度都有点慢  希望老师帮忙处理一下
@echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%p in ('dir/b *.txt') do (
set "f=%%p"
        for /f "usebackq delims=" %%j in ("!f!") do set/a n+=1
        set/a n-=2
        for /f "delims=" %%m in ('"type "!f!"|more +1"') do set/a x+=1&if !x! leq !n! echo;%%m>>!f!
        set/a n=0,x=0
set n=
(for /f "tokens=1-5*delims=;" %%a in ('type "%%p"') do (
    set "str=%%a"
    for %%i in (%%b;%%c;%%d;%%e) do (
        for /f "tokens=1*delims=." %%j in ("%%i") do (
            set "s=%%k000"
            set s=%%j.!s:~,3!
        )
            set str=!str!;!s!
     )
     for %%i in (%%f) do (
        for /f "tokens=1*delims=." %%j in ("%%i") do (
            set "s=%%k00"
            set s=%%j.!s:~,2!
        )
            set str=!str!;!s!
     )
            echo !str!
))>temp.txt

move /y temp.txt "%%p")
)
pause

TOP

谢谢楼上两位老师  感谢 学生下去再慢慢体会 虽然没有删除最后一行的语句 但是应该不难找到

TOP

这道题不适合用正则,应该用分号切割,然后处理
脚本是写给人看的,是写给用户看的,而不是写给机子看的
用户能看懂、会修改的脚本,才是好脚本。
写易懂的powershell脚本帮人解决问题,进而让用户学会自渔,吾所愿也

TOP

返回列表