标题: [文本处理] 【已解决】批处理根据文本记录,读取对应文本,限定范围求交集 [打印本页]
作者: 思想之翼 时间: 2015-12-1 20:05 标题: 【已解决】批处理根据文本记录,读取对应文本,限定范围求交集
本帖最后由 思想之翼 于 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 ...
作者: aa77dd@163.com 时间: 2015-12-1 21:12
本帖最后由 aa77dd@163.com 于 2015-12-1 21:19 编辑
在读取出的18个文本里,搜寻出7-18个文本都包含的数据(即18个文本交集,限定正确7-18个文本)
上面那句, 我不太明白
1. 这个包含的判定是以什么为单位? 以一行文本为单位吗? 就是以下面的 "0123" 或 "1234" 或者 "9876" 等等么
每个文本内有若干行数据,格式为
0123
1234
9876
...
2. 限定正确7-18个文本, 意思是说至少有 7 个文件中都包含那行数据么?
3. 只是吐槽一下, 这样的东东只是放在一个叫做 "数据库" 的文件夹里, 却没有采用 数据库技术, 至少我是不理解的
4. 对了, 没记错的话, 是阁下你吧, 阁下那个头像呢, 扔掉太不好玩了哈
作者: terse 时间: 2015-12-1 21:18
回复 1# 思想之翼
没看懂 什么是"即18个文本交集,限定正确7-18个文本"
还有这些其实都是体力活 最好一次性描述清楚
你的以前的文本处理也好 这几年 你理应可以自己处理这类问题吧 猜测你是懒得动下手指而已
言多了 抱歉
作者: 思想之翼 时间: 2015-12-1 21:31
本帖最后由 思想之翼 于 2015-12-1 22:19 编辑
回复 2# aa77dd@163.com
1、以文本内的一行数据(四位数)为判断单位
2、18个文本交集,限定正确7-18个,意思是:
搜寻出的文本1-18
有7个文本含有0123,则满足条件
有8个文本含有9876,则满足条件
有8个文本含有2584,则满足条件
有18个文本含有0059,则满足条件
将至少有 7 个文本中都包含那行数据,竖排合并,输出。
数据库技术相对高深,惧怕。
至于头像,太招摇了,惹人嫌,弃之。
作者: 思想之翼 时间: 2015-12-1 21:38
回复 3# terse
底子浅薄,自己写较复杂的批处理,力有不逮,仿佛刚学会走路的小孩要奔跑,心里急,脚不听使唤。正在通过实例业余学习批处理。问多了有点不好意思啊。
作者: aa77dd@163.com 时间: 2015-12-1 22:04
建立数据库,
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 个无结果)到结果表中
以上用粗略的语言描述的 数据库 的算法, 应该比文件处理方式效率要高, 具体代码就不要问我写不写了
作者: terse 时间: 2015-12-1 22:05
本帖最后由 terse 于 2015-12-1 22:14 编辑
回复 5# 思想之翼
文本多大 每个文本里确定没有重复数据吧
作者: 思想之翼 时间: 2015-12-1 22:08
本帖最后由 思想之翼 于 2015-12-1 22:24 编辑
回复 7# terse
D:/数据库/内,一个文本8KB左右,同一个文本内没有重复数据。
作者: terse 时间: 2015-12-1 22:54
回复 8# 思想之翼
这个问题就是18个文件里重复行问题 合并18个文件 然后提取重复次数大于7的
w7系统的话 可以试下 ps 的 group
等空的时候 试写一个代码
作者: terse 时间: 2015-12-3 00:19
回复 8# 思想之翼 - @if(0)==(0) echo off
- dir /b /s D:\数据\*.txt | cscript -NoLogo -E:JScript %0 "D:/数据库/" "D:/搜寻/"
- pause & exit
- readFile(filename){ f1.Close();
- @end
- var ting = 6;
- var ph1= WScript.Arguments.Item(0);
- var ph2= WScript.Arguments.Item(1);
- var fso = new ActiveXObject("Scripting.FileSystemObject");
- function readFile(filename, n) {
- var ar = fso.OpenTextFile(filename, n).ReadAll().replace(/\r?\n$/g,'').split("\r\n");
- return ar;
- }
-
- function uniq(ar){
- var j = 0, str = "", obj = {};
- for(var i = 0, l = ar.length; i < l; i++ ){
- var k = ar[i];
- obj[k] = obj[k] > 0 ? obj[k] + 1 :1
- }
- for (var k in obj) str += obj[k] > ting ? k + " ": "";
- return str.replace(/\s+$/g, "");
- }
-
- while (!WScript.StdIn.AtEndOfStream){
- var filename = WScript.StdIn.Readline();
- var text = readFile(filename, 1);
- for(i = 0, len = text.length; i < len; i++ ){
- var ar = [], arr = text[i].split(" ");
- for(var j = 0, l = arr.length; j < l; j++ ){
- var p = j + 1 + "\\"
- p += arr[j] + ".txt"
- ar = ar.concat(readFile(ph1 + p, 1));
- }
- var file = i + 1 + ".txt"
- var f = fso.GetBaseName(filename);
- var Folder = ph2 + f
- if (!fso.FolderExists(Folder)) fso.CreateFolder (Folder);
- var newfile = Folder + "/" + f + "_" + file;
- fso.CreateTextFile(newfile, true).Write(uniq(ar));
- }
- }
复制代码
作者: 思想之翼 时间: 2015-12-3 02:56
本帖最后由 思想之翼 于 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
作者: terse 时间: 2015-12-3 10:22
回复 11# 思想之翼
问题1 *.txt 就是所有txt
问题2 40行修改为- fso.CreateTextFile(newfile, true).WriteLine(uniq(ar));
复制代码
问题3 15-23行修改为- function uniq(ar){
- var j = 0, arr = [], obj = {};
- for(var i = 0, l = ar.length; i < l; i++ ){
- var k = ar[i];
- obj[k] = obj[k] > 0 ? obj[k] + 1 :1
- }
- for (var k in obj) {
- if (obj[k] > ting) arr[j++] = k;
- }
- return arr.join("\r\n");
- }
复制代码
作者: WHY 时间: 2015-12-3 16:11
纯练习- @if (0)==(0) echo off
- set "dstDir=D:\搜寻"
- md "%dstDir%" 2>nul
- pushd D:\数据\
- dir /b *.txt | cscript //nologo //e:jscript "%~f0" "%dstDir%\"
- pause & exit
- @end
-
- var strPath = WSH.Arguments(0);
- var fso = new ActiveXObject('Scripting.FileSystemObject');
-
- var readTextFile = function(strFile){
- var objFile = fso.OpenTextFile(strFile, 1);
- var str = objFile.ReadAll();
- objFile.Close(); objFile = null;
- return str
- }
-
- while(!WSH.StdIn.AtEndOfStream){
- var f = WSH.StdIn.ReadLine(), n = 0;
- var s = readTextFile(f).replace(/[ \t]+/g, '');
- s.replace(/\d+/g, function(s0){
- var s1 = txt = '';
- for(var i=1; i<=s0.length; i++){
- var f1 = 'D:\\数据库\\' + i + '\\' + s0.substr(i-1,1) + '.txt';
- s1 += readTextFile(f1) + '\r\n';
- }
- s1 = s1.match(/\d+/g).sort().join('\r\n') + '\r\n';
- var ar, re = /(\d+\r\n)(\1){6,}/g;
- while (ar = re.exec(s1)) { txt += ar[1] };
-
- if (txt != '') {
- var fd = f.replace(/\.txt$/i, '');
- n += 1;
- var ff = strPath + fd + '\\' + fd + '_' + n + '.txt';
- if(!fso.FolderExists(strPath + fd)) fso.CreateFolder(strPath + fd);
- fso.OpenTextFile(ff, 2, true).Write(txt);
- }
- })
- }
复制代码
作者: 思想之翼 时间: 2015-12-3 18:53
本帖最后由 思想之翼 于 2015-12-3 20:23 编辑
回复 12# terse
感谢!
问题1 不成问题,是数据源出错。
问题2 横排数据末尾回车符解决。
问题3 横排数据末尾回车符解决。
作者: 思想之翼 时间: 2015-12-3 19:53
本帖最后由 思想之翼 于 2015-12-3 20:24 编辑
回复 13# WHY
感谢您的帮助!代码完美解决问题。
作者: WHY 时间: 2015-12-3 19:58
楼主把测试数据压缩,上传到网盘吧,以方便测试代码
作者: 思想之翼 时间: 2015-12-3 20:22
回复 16# WHY
对不起了,文件夹内有一个空的新建文本,故出错。代码本身正确。谢谢您的帮助!
作者: terse 时间: 2015-12-3 22:19
本帖最后由 terse 于 2015-12-3 22:34 编辑
回复 17# 思想之翼
WIN7 系统 的话 也可试下POWERSHELL
修正一下 写入文件- $filelist = Get-ChildItem -Path D:\数据\* -Include *.txt
- $ph1 = "D:\数据库\"
- $ph2 = "D:\搜寻\"
- foreach($file in $filelist){
- $arr = cat $file.FullName
- $name = $file.Name.split(".")[0]
- $num = 0
- $new_file = $ph2 + $name + "\"
- foreach($a in $arr)
- {
- $num++
- $array = New-Object -TypeName System.Collections.ArrayList
- $ar = $a.split(" ")
- $len = $ar.Count
- for($i=0; $i -lt $len; $i++)
- {
- $ph = $ph1 +"$($i + 1)\" + $ar[$i] + ".txt"
- get-content $ph|?{$null = $array.add($_)}
- }
- $ph = $new_file + $name + "_" + $num + ".txt"
- $str = $array| group |?{$_.Count -gt 6}| select -Exp name | Out-String
- $null = new-item -type file -path $ph -Force -Value $str
- }
- }
复制代码
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |