标题: [文本处理] 【已解决】批处理如何根据指定字符匹配CSV一列数据的该行数据 [打印本页]
作者: w31575801 时间: 2021-1-26 21:06 标题: 【已解决】批处理如何根据指定字符匹配CSV一列数据的该行数据
如题,现有一个CSV文件太大,给了一些SN码,SN码对应都在CSV文件中的O列,需要找出这些码所对应的该行数据,提取出来求大神指点
作者: Batcher 时间: 2021-1-26 21:13
回复 1# w31575801
请把以下两个文件打包压缩传上来我试试:
【现有一个CSV文件】这个文件的前10行内容
【给了一些SN码】这个文件的前3行内容
作者: qixiaobin0715 时间: 2021-1-27 08:26
本帖最后由 qixiaobin0715 于 2021-1-27 09:14 编辑
这样不知行不:- @echo off
- set "SN=C3F1052G1 C3F1052G2 C3F1052G3"
- findstr "%SN%" a.csv>b.csv
- pause
复制代码
作者: w31575801 时间: 2021-1-27 09:18
回复 2# Batcher
作者: w31575801 时间: 2021-1-27 09:20
回复 2# Batcher
Log太大 直接去了一点点 您给看看 比如这一个SN (SN对应的都在O列)找到了之后就把这一行给提取出来 有很多SN,需要批量去查找再提取出来
作者: qixiaobin0715 时间: 2021-1-27 09:39
将sn.xlsx复制到文本文件sn.txt中,一行一个sn码。运行下面代码:- findstr /g:sn.txt log.csv>a.csv
复制代码
作者: Batcher 时间: 2021-1-27 09:53
回复 4# w31575801
请参考Q-04把test.bat、SN.txt、需要提取的LOG.csv文件保存为ANSI编码:
https://mp.weixin.qq.com/s/6lbb97qUOs1sTyKJfN0ZEQ- @echo off
- (for /f "skip=1 delims=" %%i in ('type "SN.txt"') do (
- findstr /c:"%%i" "需要提取的LOG.csv"
- ))>"结果.csv"
复制代码
作者: WHY 时间: 2021-1-27 10:18
文件太大的话,可以考虑第三方- gawk -F"," "NR==FNR{a[$0]=1};NR!=FNR{if(a[$15]==1)print $0}" SN.txt 需要提取的LOG.csv > result.csv
复制代码
作者: w31575801 时间: 2021-1-27 10:38
回复 8# WHY
什么第三方呀
作者: w31575801 时间: 2021-1-27 22:39
回复 7# Batcher
大佬,我要找几万个SN,这个处理的好慢呀,怎么能快一点
作者: qixiaobin0715 时间: 2021-1-28 06:49
可以用8楼的试试。http://www.bathome.net/thread-21366-1-1.html
作者: w31575801 时间: 2021-1-28 09:20
回复 8# WHY
下载了gawk双击闪退呀
作者: Batcher 时间: 2021-1-28 09:21
回复 9# w31575801
8楼用的是 gawk.exe
http://bcn.bathome.net/s/tool/index.html?key=gawk
作者: Batcher 时间: 2021-1-28 09:22
回复 10# w31575801
6楼的代码效果如何?
作者: Batcher 时间: 2021-1-28 09:23
回复 12# w31575801
不要双击gawk,把它和test.bat放在同一个目录下,再执行test.bat
作者: w31575801 时间: 2021-1-28 09:43
回复 14# Batcher
可以提取 但是文件大的话也是相当慢
作者: w31575801 时间: 2021-1-28 09:46
回复 15# Batcher
gawk这个命令出来 会有这个
作者: Batcher 时间: 2021-1-28 09:48
回复 16# w31575801
请给出量化的数据吧,比如:
SN.txt 5万行
需要提取的LOG.csv 50万行
6楼代码执行耗时 xxx
8楼代码执行耗时 xxx
作者: w31575801 时间: 2021-1-28 09:53
回复 18# Batcher
附件太大 上传不了
作者: w31575801 时间: 2021-1-28 10:00
本帖最后由 w31575801 于 2021-1-28 10:02 编辑
回复 18# Batcher
SN.TXT 一共91535个SN码 即91535行
需要查找的Log 共560000个 12GB
我是分一点点找 120MB 查找的话需要3小时左右 gawk我还没尝试 因为上夜班刚回家数据在公司
作者: xczxczxcz 时间: 2021-1-28 13:43
win10 可以写个,其它免麻烦
作者: netdzb 时间: 2021-1-28 17:04
回复 21# xczxczxcz
这么厉害,运行速度超快啊。
作者: Gin_Q 时间: 2021-1-28 17:55
本帖最后由 Gin_Q 于 2021-1-28 17:57 编辑
560000 * 91535 = 51259600000
读取一行log文件,再去 sn 里面查找匹配
不知道大家有没有更优的方法
启用多线程分块匹配应该可以优化很多
作者: 路过 时间: 2021-1-28 22:10
1一次取5600行到内存,开5个工作线程,每个线程用KMP算法搜索18307个SN码,输出含有SN码的行号;
2.等所有线程工作完了,主线程打印出行号对应的完整行>>result.csv
3.重复步骤12一百次直到log文件被搜完
作者: qixiaobin0715 时间: 2021-1-29 09:37
有个思路不知可行不:
由于源文件一行内容太长,可将sn码与源文件中含有sn码的列(可用tokens=15提取)比对,这样可以屏蔽无关的字符。如果某行含有特定的sn码,获得行号。得到所有符合条件的行号后,再按得到的行号提取行。
作者: netdzb 时间: 2021-1-29 10:56
回复 24# 路过
我们想看代码是如何写的"?"
作者: qixiaobin0715 时间: 2021-1-29 15:07
回复 1# w31575801
按照25楼的思路,用3个for循环(实际是2个,第3个是为了只显示含有sn码的列,in里面只是一行字符串),不用效率较低的findstr。不知能否提高速度:- @echo off
- setlocal enabledelayedexpansion
- (for /f "delims=" %%a in (SN.txt) do (
- for /f "delims=" %%b in (需要提取的LOG.csv) do (
- for /f "tokens=15 delims=," %%c in ("%%b") do (
- set "str=%%c"
- set "str=!str:%%a=!"
- if not "!str!"=="%%c" echo %%b
- )
- )
- ))>结果.csv
- pause
复制代码
作者: WHY 时间: 2021-1-29 20:28
本帖最后由 WHY 于 2021-1-30 13:01 编辑
回复 27# qixiaobin0715
set "s=a,b,,,c"
用delims=,分割的话,c位于第3列。实际上,在csv文件中,c位于第5列。
如果csv文件是这样的:
a,b,,,"c,d"
第5列变成 "c,d",纯批和 gawk 都会挂掉。
这样就需要正则匹配了:- ^(?:"(?>[^"]+|"")*",|[^",]*,){14}("(?>[^"]+|"")*"|[^",]*)
复制代码
当然仅适合标准的 Microsoft CSV 文档。
作者: qixiaobin0715 时间: 2021-1-29 22:01
回复 28# WHY
确实有点欠考虑,是会有很大漏洞,并且可能出现的概率也不小。但文本的复杂性太多,有时正则也会失效。
比如这样的字符串:abcd,"a,bcd","a,b"cd,"a,b""c,d","a,b"e"d,e",a"b,c"d
所以写代码时还是要根据文本的实际情况处理。
作者: WHY 时间: 2021-1-30 13:04
回复 29# qixiaobin0715
严重同意,具体问题具体分析。
作者: netdzb 时间: 2021-1-31 10:27
回复 25# qixiaobin0715
他的问题我都没有看懂。能否简化一下他的问题,比如减少字段数量。
示范文本所达到的效果。
作者: qixiaobin0715 时间: 2021-1-31 10:57
csv中带双引号的字段应该是整个字段加引号且本身存在引号的地方加上两个双引号。要表达12"ab"45,应当写成"12""ab""45"
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |