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

[文本处理] 【已解决】批处理根据文本记录,读取对应文本,限定范围求交集

本帖最后由 思想之翼 于 2015-12-3 17:56 编辑

D:/数据/内有210个文本,命名为001 002 ... 210,每个文本内有若干行18列数据,格式为 9 3 4 0 1 5 7 1 2 6 5 1 8 2 3 6 4 6
D:/数据库/内有18个子文件夹,命名为1 2 ... 18, 每个子文件夹内有10个文本,命名为 0 1 ... 9, 每个文本内有若干行数据,格式为
0123
1234
9876
...
现在欲根据D:/数据/内各文本记录的数据,读取D:/数据库/内对应文本的数据,限定范围求交集。

示例:
先看D:/数据/001.txt 第1行数据为 9 3 4 0 1 5 7 1 2 6 5 1 8 2 3 6 4 6
第1个数据是9,则读取D:/数据库/1/9.txt
第2个数据是3,则读取D:/数据库/2/3.txt
第3个数据是4,则读取D:/数据库/3/4.txt
第4个数据是0,则读取D:/数据库/4/0.txt
第5个数据是1,则读取D:/数据库/5/1.txt
第6个数据是5,则读取D:/数据库/6/5.txt
第7个数据是7,则读取D:/数据库/7/7.txt
第8个数据是1,则读取D:/数据库/8/1.txt
第9个数据是2,则读取D:/数据库/9/2.txt
第10个数据是6,则读取D:/数据库/10/6.txt
第11个数据是5,则读取D:/数据库/11/5.txt
第12个数据是1,则读取D:/数据库/12/1.txt
第13个数据是8,则读取D:/数据库/13/8.txt
第14个数据是2,则读取D:/数据库/14/2.txt
第15个数据是3,则读取D:/数据库/15/3.txt
第16个数据是6,则读取D:/数据库/16/6.txt
第17个数据是4,则读取D:/数据库/17/4.txt
第18个数据是6,则读取D:/数据库/18/6.txt
在读取出的18个文本里,搜寻出7-18个文本都包含的数据(即18个文本交集,限定正确7-18个文本)
也就是以D:/数据库/子文件夹内的文本记录的每行数据“0123"  "1234"  "9876" 为判断单位,比如在搜寻出的18个文本里,
有7个文本含有0123,则0123满足条件
有8个文本含有9876,则9876满足条件
有8个文本含有2584,则2584满足条件
有18个文本含有0059,则0059满足条件
将至少有7个文本中都包含那行数据,竖排合并,写入D:/搜寻/001/001_1.txt
再看D:/数据/001.txt第2行数据,读取对应文本,限定范围求交集,写入D:/搜寻/001/001_2.txt
直至D:/数据/001.txt最后一行数据。
如果D:/数据/001.txt只有一行数据,则读取写入一次。

D:/数据/002.txt同理读取18个文本,限定范围求交集,写入D:/搜寻/002/002_1.txt  002_2.txt ...
直至
D:/数据/210.txt同理读取18个文本,限定范围求交集,写入D:/搜寻/210/210_1.txt  210_2.txt ...

本帖最后由 terse 于 2015-12-3 22:34 编辑

回复 17# 思想之翼
WIN7 系统 的话 也可试下POWERSHELL
修正一下 写入文件
  1. $filelist = Get-ChildItem -Path D:\数据\* -Include  *.txt
  2. $ph1 = "D:\数据库\"
  3. $ph2 = "D:\搜寻\"
  4. foreach($file in $filelist){
  5.     $arr = cat $file.FullName
  6.     $name =  $file.Name.split(".")[0]
  7.     $num = 0
  8.     $new_file =  $ph2 + $name + "\"
  9.     foreach($a in $arr)
  10.     {
  11.         $num++
  12.         $array = New-Object -TypeName System.Collections.ArrayList
  13.         $ar = $a.split(" ")
  14.         $len = $ar.Count
  15.         for($i=0; $i -lt $len; $i++)
  16.        {
  17.            $ph = $ph1 +"$($i + 1)\" + $ar[$i] + ".txt"
  18.            get-content $ph|?{$null = $array.add($_)}
  19.         }
  20.         $ph = $new_file  + $name + "_" + $num + ".txt"
  21.         $str = $array| group |?{$_.Count -gt 6}| select  -Exp name | Out-String
  22.         $null = new-item -type file -path $ph -Force -Value $str
  23.     }
  24. }
复制代码
2

评分人数

TOP

回复 16# WHY

对不起了,文件夹内有一个空的新建文本,故出错。代码本身正确。谢谢您的帮助!

TOP

楼主把测试数据压缩,上传到网盘吧,以方便测试代码

TOP

本帖最后由 思想之翼 于 2015-12-3 20:24 编辑

回复 13# WHY

感谢您的帮助!代码完美解决问题。

TOP

本帖最后由 思想之翼 于 2015-12-3 20:23 编辑

回复 12# terse
感谢!
问题1  不成问题,是数据源出错。
问题2  横排数据末尾回车符解决。
问题3  横排数据末尾回车符解决。

TOP

纯练习
  1. @if (0)==(0) echo off
  2. set "dstDir=D:\搜寻"
  3. md "%dstDir%" 2>nul
  4. pushd D:\数据\
  5. dir /b *.txt | cscript //nologo //e:jscript "%~f0" "%dstDir%\"
  6. pause & exit
  7. @end
  8. var strPath = WSH.Arguments(0);
  9. var fso = new ActiveXObject('Scripting.FileSystemObject');
  10. var readTextFile = function(strFile){
  11.     var objFile = fso.OpenTextFile(strFile, 1);
  12.     var str = objFile.ReadAll();
  13.     objFile.Close(); objFile = null;
  14.     return str
  15. }
  16. while(!WSH.StdIn.AtEndOfStream){
  17.     var f = WSH.StdIn.ReadLine(), n = 0;
  18.     var s = readTextFile(f).replace(/[ \t]+/g, '');
  19.     s.replace(/\d+/g, function(s0){
  20.         var s1 = txt = '';
  21.         for(var i=1; i<=s0.length; i++){
  22.             var f1 = 'D:\\数据库\\' + i + '\\' + s0.substr(i-1,1) + '.txt';
  23.             s1 += readTextFile(f1) + '\r\n';
  24.         }
  25.         s1 = s1.match(/\d+/g).sort().join('\r\n') + '\r\n';
  26.         var ar, re = /(\d+\r\n)(\1){6,}/g;
  27.         while (ar = re.exec(s1)) { txt += ar[1] };
  28.         if (txt != '') {
  29.             var fd = f.replace(/\.txt$/i, '');
  30.             n += 1;
  31.             var ff = strPath + fd + '\\' + fd + '_' + n + '.txt';
  32.             if(!fso.FolderExists(strPath + fd)) fso.CreateFolder(strPath + fd);
  33.             fso.OpenTextFile(ff, 2, true).Write(txt);
  34.         }
  35.     })
  36. }
复制代码
1

评分人数

TOP

回复 11# 思想之翼
问题1 *.txt 就是所有txt
问题2 40行修改为
  1. fso.CreateTextFile(newfile, true).WriteLine(uniq(ar));
复制代码
问题3 15-23行修改为
  1. function uniq(ar){
  2.     var j = 0, arr = [], obj = {};
  3.     for(var i = 0, l = ar.length; i < l; i++ ){
  4.        var k =  ar[i];
  5.        obj[k] = obj[k] > 0 ? obj[k] + 1 :1
  6.     }
  7.     for (var k in obj) {
  8.         if (obj[k] > ting) arr[j++] = k;
  9.     }
  10.     return arr.join("\r\n");
  11. }
复制代码
1

评分人数

TOP

本帖最后由 思想之翼 于 2015-12-3 09:50 编辑

回复 10# terse

感谢帮助!速度快,结果正确。

有几个问题不解,恳望指教:
1、D:/数据/*.txt   代码为何只对排序在前的第一个文本运算? 若D:/数据/内有210个文本 分别运算,如何修改?
2、代码运行后的结果数据是横排输出的,若需在横排数据末尾 加回车符,修改哪里?
3、若想让数据竖排输出 末尾加回车符,修改哪里?

用第三方在横排数据末尾添加回车符  sed -i "s/$/\n/g" "D:\搜寻/001\*.txt"
或将数据横排变成竖排并添加回车符  @sed -i "s/ /\n/g;s/$/\n/g" D:/搜寻/001/*.txt

TOP

回复 8# 思想之翼
  1. @if(0)==(0) echo off
  2. dir /b /s D:\数据\*.txt | cscript -NoLogo -E:JScript %0 "D:/数据库/" "D:/搜寻/"
  3. pause & exit
  4. readFile(filename){ f1.Close();
  5. @end
  6. var ting = 6;
  7. var ph1= WScript.Arguments.Item(0);
  8. var ph2= WScript.Arguments.Item(1);
  9. var fso = new ActiveXObject("Scripting.FileSystemObject");
  10. function readFile(filename, n) {
  11.     var ar = fso.OpenTextFile(filename, n).ReadAll().replace(/\r?\n$/g,'').split("\r\n");
  12.     return ar;
  13. }
  14. function uniq(ar){
  15.     var j = 0, str = "", obj = {};
  16.     for(var i = 0, l = ar.length; i < l; i++ ){
  17.        var k =  ar[i];
  18.        obj[k] = obj[k] > 0 ? obj[k] + 1 :1
  19.     }
  20.     for (var k in obj) str += obj[k] > ting ? k + " ": "";
  21.     return str.replace(/\s+$/g, "");
  22. }
  23. while (!WScript.StdIn.AtEndOfStream){
  24.     var filename = WScript.StdIn.Readline();
  25.     var text = readFile(filename, 1);
  26.     for(i = 0, len = text.length; i < len; i++ ){
  27.         var ar = [], arr = text[i].split(" ");
  28.         for(var j = 0, l = arr.length; j < l; j++ ){
  29.             var p = j + 1 + "\\"
  30.             p += arr[j] + ".txt"
  31.             ar = ar.concat(readFile(ph1 + p, 1));
  32.         }
  33.         var  file = i + 1 + ".txt"
  34.         var f = fso.GetBaseName(filename);
  35.         var Folder = ph2 +  f
  36.         if (!fso.FolderExists(Folder)) fso.CreateFolder (Folder);
  37.         var newfile = Folder  + "/" +  f + "_" + file;
  38.         fso.CreateTextFile(newfile, true).Write(uniq(ar));
  39.     }
  40. }
复制代码
1

评分人数

TOP

回复 8# 思想之翼
这个问题就是18个文件里重复行问题 合并18个文件 然后提取重复次数大于7的
w7系统的话 可以试下 ps 的 group
等空的时候 试写一个代码

TOP

本帖最后由 思想之翼 于 2015-12-1 22:24 编辑

回复 7# terse
D:/数据库/内,一个文本8KB左右,同一个文本内没有重复数据。

TOP

本帖最后由 terse 于 2015-12-1 22:14 编辑

回复 5# 思想之翼
文本多大 每个文本里确定没有重复数据吧

TOP

建立数据库,

D:/数据/内有210个文本,命名为001 002 ... 210,每个文本内有若干行18列数据,格式为 9 3 4 0 1 5 7 1 2 6 5 1 8 2 3 6 4 6


为数据库建立 210 个表(每个表都只用一个字段), 这些表分别保存上面说的 210 个文本的内容, 行行对应

D:/数据库/内有18个子文件夹,命名为1 2 ... 18, 每个子文件夹内有10个文本,命名为 0 1 ... 9, 每个文本内有若干行数据,格式为...


再为上面说的 180 个文本文件创建 另 外 180 个表, 每个表也只用一个字段, 行行对应的方式把数据都存入数据库

210 个表中的内容也就是指定 每次 要用来检索的 18 个源表名, 算出这 18 个表名后, 将 18 个表的内容全部合并(重复的只保留一行), 并排序, 结果存入 另一个独立的表 TmpFullData 中

遍历取出 TmpFullData 表的每一行数据,  把这个数据在 那 18 个表中逐个检索并计数,   匹配计数达 7 个, 或者 不匹配计数达 12 个 , 结束, 存结果(不匹配计数达 12 个无结果)到结果表中


以上用粗略的语言描述的 数据库 的算法,  应该比文件处理方式效率要高,  具体代码就不要问我写不写了

TOP

回复 3# terse

底子浅薄,自己写较复杂的批处理,力有不逮,仿佛刚学会走路的小孩要奔跑,心里急,脚不听使唤。正在通过实例业余学习批处理。问多了有点不好意思啊。

TOP

返回列表