标题: [文本处理] 批处理如何对文本里各列数据分别除以指定数值 [打印本页]
作者: meiszp 时间: 2016-9-27 14:01 标题: 批处理如何对文本里各列数据分别除以指定数值
本帖最后由 meiszp 于 2016-9-29 11:18 编辑
文件夹下有许多数据文件(扩展名为txt或指定),文件内容为多列数据(下面为7列,但实际可能更多),想对每列除以一个数,比如第1列除以10,第2列除以20等等。
求大侠赐教。
-6.70552254e-007 4.56646750e+005 6.89739219e+004 -3.81691500e+005 2.08684141e+005 -4.90864719e+005 3.10406906e+005
5.00000007e-002 4.61931250e+005 1.36446094e+005 -3.59222750e+005 2.07390922e+005 -4.75073250e+005 3.40052250e+005
9.99993235e-002 4.98387563e+005 2.60942938e+005 -3.52485344e+005 2.02917281e+005 -4.60640719e+005 3.66940344e+005
1.50000006e-001 5.08161344e+005 3.97039625e+005 -3.58057656e+005 1.97205422e+005 -4.43923438e+005 3.92823375e+005
1.99999332e-001 4.81562063e+005 5.06175219e+005 -3.86291063e+005 1.91434969e+005 -4.22848281e+005 4.17620406e+005
2.50000000e-001 4.46009031e+005 5.63322500e+005 -4.38631031e+005 1.88274859e+005 -3.97913656e+005 4.41026063e+005
2.99999326e-001 4.34343250e+005 5.40127375e+005 -4.90687344e+005 1.88438328e+005 -3.70999531e+005 4.62318875e+005
3.49999994e-001 4.58196469e+005 4.70192063e+005 -5.18217250e+005 1.90427172e+005 -3.43401031e+005 4.79834125e+005
3.99999321e-001 4.85120313e+005 3.84186875e+005 -5.56579813e+005 1.93310938e+005 -3.15954906e+005 4.95534531e+005
数据文件见网盘 http://share.weiyun.com/6bdcb931f8703b3830a9c9d711f5e053
作者: pcl_test 时间: 2016-9-27 14:54
本帖最后由 pcl_test 于 2016-9-29 23:40 编辑
- #*第三方http://www.bathome.net/s/tool/index.html?key=gawk
- #*&cls&dir /a-d/b *.txt|gawk -f "%~f0"&pause&exit
- BEGIN{
- folder="结果";
- system("md \""folder"\" 2>nul");
- list="1=10,2=20,3=30,4=40,5=50,6=60,7=70,8=80,9=90,10=100,11=110,12=120";
- #此处定义每列的除数,如1=10表示第1列除以10,2=20表示第2列除以20……以此类推,
- #只要定义到最大的列即可,如最多有20列,则定义到20=除数,
- #如果不对某列操作,则该列不需定义除数或定义除数为1
- split(list,a,",");
- for(i=1;i<=length(a);i++){
- split(a[i],b,"=");
- map[b[1]]=b[2];
- }
- while(getline file>0){
- while(getline<file>0){
- if($0~/^[[:space:]]*$/){
- print>folder"\\New_"file;
- }else{
- for(i=1;i<=NF;i++){
- printf i<NF?"%.8e ":"%.8e\n",map[i]==""?$i:$i/map[i]>folder"\\New_"file;
- }
- }
- }
- }
- }
复制代码
作者: meiszp 时间: 2016-9-27 15:38
本帖最后由 meiszp 于 2016-9-27 15:47 编辑
回复 2# pcl_test
恕我小白,请问第一行是要我安装gawk?第二行是让我在DOS窗口复制下面命令运行吗?
&cls&dir /a-d/b *.txt|gawk -f "%~f0"&pause&exit
有没有纯批的命令呢?谢谢!
作者: pcl_test 时间: 2016-9-27 19:24
本帖最后由 pcl_test 于 2018-4-12 15:08 编辑
- powershell -c "dir *.txt|?{$_ -is [IO.FileInfo]}|%%{gc $_|%%{$a=($_.trim() -split '\s+');('{0:e8} {1:e8} ' -f ($a[0]/10),($a[1]/20))+($a[2..($a.length-1)] -join ' ')}|out-file ('New_'+$_.name) -encoding default}"
- pause
复制代码
作者: 523066680 时间: 2016-9-27 19:58
本帖最后由 523066680 于 2016-9-27 20:11 编辑
Perl,安装请咨询搜索引擎。- open READ, "<:raw", "data.txt";
-
- my @divi = map { $_ * 10 } (1 .. 20); #10 20 30 ... 200
- my $i;
-
- while ($e = <READ> )
- {
- $e =~s/^\s+//; #开头空格清除
- $e =~s/\r?\n$//; #换行符清除
- $i = 0;
- @arr = map { $divi[$i++] * $_ } split(/\s+/, $e);
- grep { printf("% e ", $_) } @arr;
- print "\n";
- }
-
- close READ;
复制代码
相比之下我这个有点肿,可能有些知识没掌握
输出结果没有验证过- -6.705523e-006 9.132935e+006 2.069218e+006 -1.526766e+007 1.043421e+007 -2.945188e+007 2.172848e+007
- 5.000000e-001 9.238625e+006 4.093383e+006 -1.436891e+007 1.036955e+007 -2.850440e+007 2.380366e+007
- 9.999932e-001 9.967751e+006 7.828288e+006 -1.409941e+007 1.014586e+007 -2.763844e+007 2.568582e+007
- 1.500000e+000 1.016323e+007 1.191119e+007 -1.432231e+007 9.860271e+006 -2.663541e+007 2.749764e+007
- 1.999993e+000 9.631241e+006 1.518526e+007 -1.545164e+007 9.571748e+006 -2.537090e+007 2.923343e+007
- 2.500000e+000 8.920181e+006 1.689968e+007 -1.754524e+007 9.413743e+006 -2.387482e+007 3.087182e+007
- 2.999993e+000 8.686865e+006 1.620382e+007 -1.962749e+007 9.421916e+006 -2.225997e+007 3.236232e+007
- 3.500000e+000 9.163929e+006 1.410576e+007 -2.072869e+007 9.521359e+006 -2.060406e+007 3.358839e+007
- 3.999993e+000 9.702406e+006 1.152561e+007 -2.226319e+007 9.665547e+006 -1.895729e+007 3.468742e+007
复制代码
作者: happy886rr 时间: 2016-9-27 21:58
本帖最后由 happy886rr 于 2016-9-28 22:41 编辑
回复 1# meiszp
纯批模拟科学计数法- @echo off
- SETLOCAL ENABLEDELAYEDEXPANSION
- (for /f "tokens=1,2,*" %%a in ('type test.txt') do (
- for /f "tokens=1,2 delims=e" %%A in ("%%a") do (
- set "str=%%B"
- if "!str:~0,1!"=="-" (
- set/a "str=1!str:~1!+1"&set "str=-!str:~-3!"
- ) else (
- if "!str!"=="+000" (
- set "str=-001"
- ) else (
- set/a "str=1!str:~!-1"&set "str=+!str:~-3!"
- )
- )
- set "lie1= %%Ae!str!"
- )
- for /f "tokens=1,2 delims=e" %%A in ("%%b") do (
- set "str=%%B"&set "ptr=%%A"&set "ptr=!ptr:.=!"
- if !ptr! geq 200000000 (set/a ptr/=2) else (set/a ptr=!ptr!0/2)
- if !ptr! geq 500000000 (set Mark=1) else (set Mark=0)
- if "!str:~0,1!"=="-" (
- set/a "str=1!str:~!+1+Mark"&set "str=-!str:~1!"
- ) else (
- if "!str!"=="+000" (
- if !Mark! equ 1 (set "str=-001") else (set "str=-002")
- ) else (
- set/a "str=1!str:~1!-1-Mark"&set "str=+!str:~1!"
- )
- )
- set "lie2= !ptr:~0,1!.!ptr:~1!e!str!"
- )
- echo !lie1:~-16! !lie2:~-16! %%c
- ))>new.txt
- start new.txt
- set/p=修改完毕!
复制代码
作者: codegay 时间: 2016-9-28 06:02
按CSV文件的格式存文件,保持格式统一。不要为了视觉对齐,用空格补全对齐文件内容。
作者: WHY 时间: 2016-9-28 19:43
PowerShell- $str = [IO.File]::ReadAllText('D:\Test\a.txt', [Text.Encoding]::Default);
- [regex]::Replace($str, '(?m)^(\s*\S+)', {param($m); ($m.Value/10).ToString('e8')})
复制代码
作者: meiszp 时间: 2016-9-28 22:21
本帖最后由 pcl_test 于 2016-9-28 22:27 编辑
回复 4# pcl_test
大神,您好!您写的大代码我复制新建了个.bat文件运行,结果如下。多了一列,结果也不是我想要的。还有就是每列都要除以一个数字,比如共有20列,1列/1、2列/2、3列/3……20列/20。
作者: meiszp 时间: 2016-9-28 22:22
回复 5# 523066680
谢谢,小白还是喜欢纯批,不用安装其他东西。
作者: pcl_test 时间: 2016-9-28 22:23
回复 9# meiszp
把你测试的文本打包发上来看看
作者: meiszp 时间: 2016-9-28 22:27
回复 11# pcl_test
不在自己的电脑上,我明天上传吧。麻烦大神了。
作者: meiszp 时间: 2016-9-28 22:27
回复 6# happy886rr
谢谢!完全看不懂。在代码中看不出我要除的数字。您写的大代码我复制新建了个.bat文件运行,没有结果。
作者: meiszp 时间: 2016-9-28 22:29
回复 8# WHY
谢谢!不过每列没有除以一个数。
作者: happy886rr 时间: 2016-9-28 22:30
本帖最后由 happy886rr 于 2016-9-28 22:39 编辑
回复 13# meiszp
没有结果那就对了,我只修改名字为test.txt的文件,对了,我还没有加pause。速度太快,结果一闪而过。已添加pause,请在原楼复制吧。
作者: pcl_test 时间: 2016-9-28 22:31
回复 12# meiszp
不用了,你就用你顶楼的数据测试,每行开头的空格去掉,不知你原数据每行开头是否空格?
作者: meiszp 时间: 2016-9-28 22:42
本帖最后由 pcl_test 于 2018-4-12 15:09 编辑
回复 16# pcl_test
是空格的原因,试验了下没有问题,不过不记得有没有空格, 明天看看。
还有大神,我举的例子只对前两列除了个数,但有好多列
作者: happy886rr 时间: 2016-9-28 22:44
回复 17# meiszp
已添加打印输出,请到6楼重新复制。
作者: meiszp 时间: 2016-9-28 22:49
回复 18# happy886rr
谢谢,可以对例子实现。
但这个好像只能对文件名为test.txt的一个文件使用。我是有几百个这样的数据文件,每个文件有好多列,最多的是20列,每列可能都会除以一个不确定数,所以我要穷举出所以列。
作者: happy886rr 时间: 2016-9-28 22:52
回复 19# meiszp
抱歉,你什么参数都不确定,我也无能为力了。
作者: pcl_test 时间: 2016-9-28 22:54
本帖最后由 pcl_test 于 2018-4-12 15:10 编辑
回复 17# meiszp
只针对顶楼7列的数据有效- powershell -c "dir 1.txt|?{$_ -is [IO.FileInfo]}|%%{gc $_|%%{$a=($_.Trim() -split '\s+');'{0:e8} {1:e8} {2:e8} {3:e8} {4:e8} {5:e8} {6:e8}' -f ($a[0]/10),($a[1]/20),($a[2]/30),($a[3]/40),($a[4]/50),($a[5]/60),($a[6]/70)}|out-file ('New_'+$_.name) -encoding default}"
- pause
复制代码
作者: meiszp 时间: 2016-9-28 22:58
回复 20# happy886rr
每列除的数可以先代替,用时自己修改。比如有20列,1列/1、2列/2、3列/3……20列/20。
如果有10列,是不是把代码里的20,也可能是个控制代码,修改到10,后面相应的1列/1、2列/2、3列/3……10列/10。
作者: WHY 时间: 2016-9-28 23:13
PowerShell- $str = [IO.File]::ReadAllText('D:\Test\a.txt', [Text.Encoding]::Default);
- [regex]::Replace($str, "[^`r`n]+", {param($a); $i=0; [regex]::Replace($a.Value, '\S+', {param($b); ($b.Value/++$i).ToString('e8')})})
复制代码
作者: meiszp 时间: 2016-9-28 23:25
回复 21# pcl_test
谢谢!如果不是7列的话,应该是更改下面红色部分了。我试验了下没问题,非常感谢。
powershell -c "dir *.txt|?{$_ -is [IO.FileInfo]}|%%{gc $_|%%{$a=($_.Trim() -split '\s+');'{0:e8} {1:e8} {2:e8} {3:e8} {4:e8} {5:e8} {6:e8}' -f ($a[0]/10),($a[1]/20),($a[2]/30),($a[3]/40),($a[4]/50),($a[5]/60),($a[6]/70)}|out-file ('New_'+$_.name) -encoding ascii}"
pause
作者: meiszp 时间: 2016-9-28 23:31
回复 23# WHY
谢谢!在D:\Test\a.txt下试用了下,没什么改变,没有对每列除以一个数。
作者: pcl_test 时间: 2016-9-29 00:02
本帖最后由 pcl_test 于 2018-4-12 15:10 编辑
$map=@{'0'=10;'1'=20;'2'=30;'3'=40;'4'=50;'5'=60;'6'=70;'7'=80;'8'=90;'9'=100;'10'=110;'11'=120;……}
此处定义每列的除数,如'0'=10表示第1列除以10,'1'=20表示第2列除以20……以此类推,只要定义到最大的列即可,如最多有20列,则定义到'19'=除数,如果不对某列操作,则该列不需定义除数或定义除数为1- powershell -c "$map=@{'0'=10;'1'=20;'2'=30;'3'=40;'4'=50;'5'=60;'6'=70;'7'=80;'8'=90;'9'=100;'10'=110;'11'=120};dir *.txt|?{$_ -is [IO.FileInfo]}|%%{gc $_|%%{if($_ -match '^\s*$'){$_}else{$a=($_.trim() -split '\s+');$line='';for($i=0;$i -le ($a.length-1);$i++){if($map.ContainsKey(''+$i)){$line+=' '+('{0:e8}' -f ($a[$i]/$map[''+$i]))}else{$line+=' '+$a[$i]}};$line.trim()}}|out-file ('New_'+$_.name) -encoding default}"
- pause
复制代码
作者: /zhqsystem/zhq 时间: 2016-9-29 03:32
也许有错误,错误在计算方法上也许错误文化有限看不懂这个数值
一般可以看得懂代码和移位类似,支持超过for变量占用超出分列,但是不能超过最大变量字符数
只看方法吧
- @echo off&&setlocal enabledelayedexpansion
- set "[set]=10 20 30 40 50 60 80"
- for /l %%n in (1,1,8192)do (
- for /f "tokens=1,* delims= " %%i in ("![set]!")do (
- set "[set]=%%j"&&set/a "[set][n]+=1"
- for /f "delims=" %%n in ("![set][n]!")do set "[set][new][%%n]=%%i"
- )
- )
- for /f "delims=" %%i in ('type "新建文本文档 (4).txt"')do (
- set "[type]=%%i"&&set "[type][n]="&&set "[true]="
- for /l %%n in (1,1,![set][n]!)do (
- for /f "tokens=1,* delims= " %%i in ("![type]!")do (
- set "[type]=%%j"&&set/a "[type][n]+=1"
- for /f "delims=" %%n in ("![type][n]!")do (
- set "[calc]=%%i/![set][new][%%n]!"
- call :[calc]
- if defined [true] (
- set "[true]=![true]! ![calc][new]!"
- )else (
- set "[true]=![calc][new]!"
- )
- )
- )
- )
- echo/
- echo,![true]!
- )
- pause
- exit
- :[calc]
- for /f "delims=" %%c in ('mshta.exe "vbscript:createobject("scripting.filesystemobject").getstandardstream(1).write(%[calc]%)(close)"') do set "[calc][new]=%%~c"
- goto:eof
复制代码
作者: WHY 时间: 2016-9-29 10:01
这个帖子真的特么火了吗?- @echo off
- set "r='\d+\.?\d*[Ee][-+]\d{3}'"
- md new\ 2>nul
- PowerShell -c "dir *.txt|%%{$str=[IO.File]::ReadAllText($_,[Text.Encoding]::Default);[regex]::Replace($str,\"[^^`r`n]+\",{param($a);$i=0;[regex]::Replace($a.Value,%r%,{param($b);($b.Value/++$i).ToString('e8')})})>('new\'+$_.Name)}"
- pause
复制代码
作者: codegay 时间: 2016-9-29 10:13
回复 27# /zhqsystem/zhq
科学计数法
作者: 523066680 时间: 2016-9-29 10:39
本帖最后由 523066680 于 2016-9-29 10:41 编辑
回复 523066680
谢谢,小白还是喜欢纯批,不用安装其他东西。
meiszp 发表于 2016-9-28 22:22
哈哈哈,这句话说的好任性,潜台词是:
小白还是喜欢各位大大用纯批处理帮我服务,不要安装其他东西,that's too easy,you guys must pay more time.
作者: meiszp 时间: 2016-9-29 23:16
回复 26# pcl_test
多谢大神,数据已经上传了,前面是有空格的,但21楼和26楼代码完美解决,26楼的更简洁。
还想好奇的问问,如果每列除的数相同,是不是还可以简单些?
作者: meiszp 时间: 2016-9-29 23:19
回复 28# WHY
谢谢!您的代码似乎也对文件数据做了修改,但看不懂,如果想更改除数,不知道怎么做。
作者: pcl_test 时间: 2016-9-29 23:38
本帖最后由 pcl_test 于 2016-9-29 23:39 编辑
回复 31# meiszp
26楼- powershell -c "dir *.txt|?{$_ -is [IO.FileInfo]}|%%{gc $_|%%{if($_ -match '^\s*$'){$_}else{$a=($_.trim() -split '\s+');$line='';for($i=0;$i -le ($a.length-1);$i++){$line+=' '+('{0:e8}' -f ($a[$i]/指定的共同除数))};$line.trim()}}|out-file ('New_'+$_.name) -encoding ascii}"
- pause
复制代码
28楼($b.Value/++$i)改为($b.Value/指定的共同除数)
作者: codegay 时间: 2016-9-30 09:01
python 的pandas 处理起来真的是完全不费力啊。
pandas 是一个python用来进行数据处理和计算的库,提供了很多非常简单友好易用的数据处理相关的接口.
处理单个文件的代码示例:- #2016年9月30日 08:39:27 codegay
-
- from pandas import *
-
- csv = read_csv("F31_03.txt",sep='\s+',header=None)
- s = Series([10,20,30,40,50,60,70])
-
- newcsv = csv / s #csv 中的数据每列除以 s中对应的数值
-
- print(newcsv)
复制代码
作者: WHY 时间: 2016-10-10 22:17
发现win8.1(PowerShell 4.0)与 win7(PowerShell 2.0)在脚本块中定义变量有区别
脚本块中的变量作用域原本应该是Local性质的,但win7把它当作Global传递,混乱了。
以下代码win7、win8.1测试通过(第1列/10;第2列/20;第3列/30;......):- @echo off
- set "r='\d+\.?\d*[Ee][-+]\d{3}'"
- set "s=[IO.File]::ReadAllText($_,[Text.Encoding]::Default)"
- md new\ 2>nul
- PowerShell -c "dir *.txt|%%{[regex]::Replace(%s%,\"[^^`r`n]+\",{param($a,$global:i=0);[regex]::Replace($a.Value,%r%,{param($b);($b.Value/++$global:i/10).ToString('e8')})})>('new\'+$_.Name)}"
- pause
复制代码
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |