标题: [文本处理] 请老师抽空帮写一个批处理文本合并去重复(已解答,谢谢各位老师的帮助!) [打印本页]
作者: PCL0769 时间: 2021-10-4 07:36 标题: 请老师抽空帮写一个批处理文本合并去重复(已解答,谢谢各位老师的帮助!)
本帖最后由 PCL0769 于 2021-10-12 17:03 编辑
01文件夹内有以下文本
1.txt
2.txt
3.txt
4.txt
......
N.txt
02文件夹内有以下文本
1.txt
2.txt
3.txt
4.txt
......
N.txt
03文件夹内有以下文本
1.txt
2.txt
3.txt
4.txt
......
N.txt
04文件夹内有以下文本
1.txt
2.txt
3.txt
4.txt
......
N.txt
05文件夹内有以下文本
........
有N个文件夹
请帮忙写一个将以上N个文件夹中的N个同名的文本合并然后生成一个新的文件夹,文件夹中同样生成合并后同名的文本
合并文件夹内有以下文本
1.txt
2.txt
3.txt
4.txt
......
N.txt
以下是原文档中的小部分格式内容,需要在合并后新生成的文本中去除不完整的行,去重复和去特定行的语句,谢谢!
SZ300951 20210226 4727036
SZ300999 20210226 -201125534
SZ301000 20210(原文本中少部分会有这种不完整的行,在合并后新生成的文本中将不完整的行去除)
SZ300 (原文本中少部分会有这种不完整的行,在合并后新生成的文本中将不完整的行去除)
SZ138811-QQ84299 20210226 0 (原文本中少部分会有此行,20210226 原文本中是按日期的一个变量,现需在新合并后生成的文本中将此行去除)
合并时能不能将记事本中的字符替换,替换条件如下:
SH替换成1|
SZ替换成0|
SZ300951 20210226之间的空格替换成|
20210226 4727036之间的空格替换成|
合并后的最终文本内容格式:
0|000001|20210104|45971388
1|600004|20210104|22269128
另:
以下是完整的两行。
SZ300951 20210226 4727036
SZ300999 20210226 -201125534
以下是不完整的两行,如果不好写就忽略此条件也行
SZ301000 20210
或者
SZ300
以下是多余无用的行,此行内容不需要 (20210226 是按日期变化的变量)
SZ138811-QQ84299 20210226 0
不完整的行是原记事本偶尔某几个记事本中才会出现,不是所有的都会出现。
生成新的合并记事本时将这些不完整的去除,不完整的行不生成到这个新的合并记事本中。
请老师抽空帮写一个批处理,谢谢!
作者: newswan 时间: 2021-10-4 11:21
不完整的行,只有 1 列 2 列? 还是 列中 数据不完整?
作者: PCL0769 时间: 2021-10-4 12:09
本帖最后由 PCL0769 于 2021-10-4 12:55 编辑
回复 2# newswan
老师好!
SZ300951 20210226 4727036
SZ300999 20210226 -201125534
以上是完整的两行。
以下是不完整的两行,如果不好写就忽略此条件也行
SZ301000 20210
或者
SZ300
以下是多余无用的行,此行内容不需要 (20210226 是按日期变化的变量)
SZ138811-QQ84299 20210226 0
不完整的行是原记事本偶尔某几个记事本中才会出现,不是所有的都会出现。
生成新的合并记事本时将这些不完整的去除,不完整的行不生成到这个新的合并记事本中
作者: newswan 时间: 2021-10-4 13:28
本帖最后由 newswan 于 2021-10-4 13:41 编辑
用了第三方命令 sed- @echo off
- setlocal ENABLEDELAYEDEXPANSION
-
- set sour=aaa
- set dest=bbb
- del %dest%\*.txt
-
- set exclude=20210226
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%sour%\*.txt"`) do (
- sed -r -n -e "/\w+\s+\w+\s+\w+/p" -e "/%exclude%/d" "%%~fa">> "%dest%\%%~na.txt"
- )
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%dest%\*.txt"`) do (
- set _file_=%%~fa
- for /f "usebackq tokens=* delims=" %%a in ("%_file_%") do (
- set __%%a=%%a
- )
-
- (
- for /f "usebackq tokens=2 delims==" %%a in (`set __`) do (
- echo %%a
- )
- ) > "%_file_%"
- rem notepad"%_file_%"
- )
复制代码
作者: newswan 时间: 2021-10-4 13:36
findstr 支持正则太差,所以用了sed
作者: PCL0769 时间: 2021-10-4 13:41
回复 4# newswan
老师好!
是BAT吗?双击后只是闪了一下,没运行。
作者: newswan 时间: 2021-10-4 13:42
本帖最后由 newswan 于 2021-10-4 13:44 编辑
回复 6# PCL0769
可能 没有 sed
论坛里下载一个,放到 c:\windows
http://www.bathome.net/thread-36408-1-1.html
作者: PCL0769 时间: 2021-10-4 13:50
本帖最后由 PCL0769 于 2021-10-4 14:03 编辑
回复 7# newswan
老师好!
看到链接了,
正式版 - http://www.bathome.net/s/tool/index.html
测试版 - http://bcn.bathome.net/s/tool/index.html
是下载其中任一一个都行吗?谢谢老师!
没找到sed下载,都是SED应用方面的,因为级别不够一小时只能跟5帖
还是闪退,没运行
作者: newswan 时间: 2021-10-4 13:53
回复 8# PCL0769
http://bcn.bathome.net/tool/4.8/sed.exe
作者: newswan 时间: 2021-10-4 14:16
我测试正确的,你自己调试一下
set sour=aaa 源路径
set dest=bbb 目的路径
set exclude=20210226 排除列表
作者: PCL0769 时间: 2021-10-4 14:33
回复 11# newswan
找不到 C:\*.txt
文件名、目录名或卷标语法不正确。
@echo off
setlocal ENABLEDELAYEDEXPANSION
set sour=C:\Users\Administrator\Desktop\15单\新建文件夹
set dest=C:\Users\Administrator\Desktop\15单\新建文件夹2
del %dest%\*.txt
for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%sour%\*.txt"`) do (
sed -r -n -e "/\w+\s+\w+\s+\w+/p" -e "/%exclude%/d" "%%~fa">> "%dest%\%%~na.txt"
)
for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%dest%\*.txt"`) do (
set _file_=%%~fa
for /f "usebackq tokens=* delims=" %%a in ("%_file_%") do (
set __%%a=%%a
)
(
for /f "usebackq tokens=2 delims==" %%a in (`set __`) do (
echo %%a
)
) > "%_file_%"
notepad "%_file_%"
)
作者: newswan 时间: 2021-10-4 14:44
本帖最后由 newswan 于 2021-10-4 15:34 编辑
- @echo off
- setlocal ENABLEDELAYEDEXPANSION
-
- set sour=C:\Users\admin\Desktop\New folder (2)\aaa
- set dest=C:\Users\admin\Desktop\New folder (2)\bbb
- set exclude=20210226
-
- del "%dest%\*.txt"
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%sour%\*.txt"`) do (
- sed -r -n -e "/\w+\s+\w+\s+\w+/p" -e "/%exclude%/d" "%%~fa">> "%dest%\%%~na.txt"
- )
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%dest%\*.txt"`) do (
- for /f "usebackq tokens=* delims=" %%a in ("%%~fa") do (
- set __%%a=%%a
- )
-
- (
- for /f "usebackq tokens=2 delims==" %%a in (`set __`) do (
- echo %%a
- )
- ) > "%%~fa"
- notepad.exe "%%~fa"
- )
复制代码
作者: newswan 时间: 2021-10-4 15:12
本帖最后由 newswan 于 2021-10-4 15:32 编辑
powershell 好一些- $sour = "aaa"
- $dest = "bbb"
- $exclude = "20210227"
-
- Remove-Item $dest\*.txt
-
- Get-ChildItem -path $sour *.txt -Recurse | foreach-object {
- ( get-content $_.fullname ) -match "\w+\s+\w+\s+[-]?\w+" -notmatch $exclude | out-file -append $dest\$_
- }
-
- Get-ChildItem -path $dest *.txt | foreach-object {
- $a = get-content $_.fullname | sort-object -unique
- $a | out-file $dest\$_
- notepad.exe $dest\$_
- }
复制代码
作者: newswan 时间: 2021-10-4 15:33
本帖最后由 newswan 于 2021-10-4 15:37 编辑
目录是这样的- ├───aaa
- │ ├───01
- │ └───02
- └───bbb
复制代码
刚才 网站 拒绝登陆
作者: qixiaobin0715 时间: 2021-10-4 15:50
探讨关于在for循环中使用set name几个问题。
我也在关注如何解决此帖中问题,基本想法和你类似。其中有几个问题未考虑成熟:
1.当没有变量引导符时,比如set __,可以显示所有以__开头的变量,并以通常顺序显示;
2.当循环设置变量,并使用这些变量处理完成后,再次循环设置变量时,前面设置的变量并不会自动消失,还会存在,直到将它们设置为空值或是退出cmd后。
所以,使用set name来处理帖子中的问题时,如果没有顺序要求应当可行。并且要考虑在下次循环前清空前面的变量值。
我自己未想到解决的办法。
作者: newswan 时间: 2021-10-4 16:04
本帖最后由 newswan 于 2021-10-4 16:08 编辑
回复 15# qixiaobin0715
欠考虑,如果是单文件去重,需要清除变量
谢谢!!!
作者: newswan 时间: 2021-10-4 16:07
本帖最后由 newswan 于 2021-10-4 18:52 编辑
- @echo off
- setlocal ENABLEDELAYEDEXPANSION
-
- set sour=C:\Users\admin\Desktop\New folder (2)\aaa
- set dest=C:\Users\admin\Desktop\New folder (2)\bbb
- set exclude=20210226
-
- del "%dest%\*.txt"
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%sour%\*.txt"`) do (
- sed -r -n -e "/\w+\s+\w+\s+\w+/p" -e "/%exclude%/d" "%%~fa">> "%dest%\%%~na.txt"
- )
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%dest%\*.txt"`) do (
- for /f "usebackq tokens=2 delims==" %%a in (`set __ 2^>nul`) do (
- set %%a=
- )
- for /f "usebackq tokens=* delims=" %%a in ("%%~fa") do (
- set __%%a=1
- )
-
- (
- for /f "usebackq tokens=2 delims==" %%a in (`set __`) do (
- echo %%a
- )
- ) > "%%~fa"
- notepad.exe "%%~fa"
- )
复制代码
作者: PCL0769 时间: 2021-10-4 18:02
本帖最后由 PCL0769 于 2021-10-4 18:12 编辑
回复 15# qixiaobin0715
老师好!
现在用老师你上次帮写的D:/ABC合并,然后用vbs SZ替换为0| SH 替换为1| 空格替换成| SZ138...-QQ...替换成空格(此处还是留有不全的一行数据)。
分两步完成,首先用bat合并 ,然后vbs替换,这么做的结果是会留有不完整的行数据
0|301075|20210930|44406634
1|601077|20210930|-67302759
0||20210930|0 (0|后面的空格就是SZ139...-QQ...替换后的空数值)
newswan老师好!
楼上的代码还是闪退。
谢谢!
作者: newswan 时间: 2021-10-4 18:54
我这里运行是正确的,你自己调试吧
作者: PCL0769 时间: 2021-10-4 19:13
回复 19# newswan
老师好!刚刚传了部分文本到云盘。
链接:
https://pan.baidu.com/s/1hqJLvFBn6n1Y-g9518TVyw
提取码:
9ewg
作者: newswan 时间: 2021-10-4 20:58
回复 20# PCL0769
数据量很大,powershell 效率高些- $sour = "D:\share\tech\New folder (2)\aaa"
- $dest = "D:\share\tech\New folder (2)\ccc"
- $exclude = "20210227"
-
- Remove-Item $dest\*.txt
-
- get-date
-
- Get-ChildItem -path $sour *.txt -Recurse | foreach-object {
- $_.fullname
- ( get-content $_.fullname ) -match "\w+\s+\w+\s+[-]?\w+" -notmatch $exclude -replace "SZ","1" -replace "SH","0" -replace "\s+","|" | out-file -append $dest\$_
- }
-
- get-date
-
- Get-ChildItem -path $dest *.txt | foreach-object {
- $_.fullname
- $a = get-content $_.fullname | sort-object -unique
- $a | out-file $dest\$_
- }
-
- get-date
复制代码
作者: Batcher 时间: 2021-10-4 21:41
回复 18# PCL0769
建议以后不要再说“不行”、“一闪而过”、“没有反应”之类的话,因为这对于想要给你进一步帮助的人来说没有任何意义。希望大家都能学会的一个知识点是:如何查看代码的报错信息。
如果你在执行.bat脚本,请参考Q-01观察一下哪行代码在报错以及详细的报错信息:
https://mp.weixin.qq.com/s/6lbb97qUOs1sTyKJfN0ZEQ
如果你在执行.ps1脚本,请参考:
http://bbs.bathome.net/thread-31071-1-1.html
作者: PCL0769 时间: 2021-10-4 22:56
回复 22# Batcher
好的谢谢老师提醒,以后注意。
双击运行时,只见到闪了一下,来不及看批处理出现什么问题就退出界面,小白一枚,还请老师见谅!
作者: PCL0769 时间: 2021-10-4 23:07
本帖最后由 PCL0769 于 2021-10-4 23:08 编辑
回复 21# newswan
老师好!谢谢!
请教老师,后缀是用bat吗?
源数据放在桌面C:\Users\Administrator\Desktop\15单\金额16\补数据文件夹下
这里是不是要这么修改:
$sour = "C:\Users\Administrator\Desktop\15单\金额16\补数据\aaa"
$dest = "C:\Users\Administrator\Desktop\15单\金额16\补数据\ccc"
按这修改后还是闪退,是不是在最后加上PUSH就不会出现闪退,实在太快退出界面不知道没运行起来是什么原因。
作者: newswan 时间: 2021-10-4 23:48
本帖最后由 newswan 于 2021-10-5 00:56 编辑
回复 24# PCL0769
使用 powershell 看这里
http://www.bathome.net/thread-59270-1-1.html
如果批处理,用第三方命令 sort 排序去重,效率高。- ├───aaa <--- 数据源
- ├───01
- └───02
复制代码
作者: qixiaobin0715 时间: 2021-10-5 11:26
回复 21# newswan
确实是这样。批处理代码倒是写出来了,真是慢的让人忍受不了。
作者: newswan 时间: 2021-10-5 12:00
本帖最后由 newswan 于 2021-10-5 12:23 编辑
回复 26# qixiaobin0715
去重 效率比较
gnu:sort = vbs > powershell > 批处理
第三方命令,有的和 windows 自带命令重名
第三方命令保存到单独目录,然后把这个路径添加到 %path% 的前面部分
比如- set Path=C:\msys64\usr\bin;%Path%
复制代码
作者: qixiaobin0715 时间: 2021-10-5 12:27
回复 27# newswan
批处理处理大文本文件速度确实慢,就楼主提供的文件测试,for /f 变量替换速度也不行。
作者: newswan 时间: 2021-10-5 13:12
本帖最后由 newswan 于 2021-10-5 13:15 编辑
回复 28# qixiaobin0715
vbs 不会,但是 powershell 效率低,是很无语的。ms 一向是这样
批处理+第三方 有时候也麻烦。
作者: PCL0769 时间: 2021-10-5 13:19
本帖最后由 PCL0769 于 2021-10-5 13:40 编辑
回复 29# newswan
老师好!
下面是从论坛组装的VBS替换
Set WshShell = CreateObject("Wscript.Shell")
WshShell.Run "cmd /c dir /s/b *.txt > list.txt",vbHide
Wscript.Sleep 1000
sFile = "list.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = objFSO.OpenTextFile(sFile,1)
Do While Not oFile.AtEndOfStream
strLine = oFile.ReadLine
If Len(strLine) > 0 Then
Set File = objFSO.OpenTextFile(strLine, 1)
aryLines = File.ReadAll
File.Close
aryLines = Replace(aryLines, "SZ", "0|")
aryLines = Replace(aryLines, "SH", "1|")
Set File = objFSO.OpenTextFile(strLine, 2)
File.Write aryLines
File.Close
End If
Loop
oFile.Close
objFSO.DeleteFile sFile
Set objFSO = Nothing
这个替换效率还行,就是得分两步,一:bat合并 二:vbs替换
vbs将不完整的行和那个手机号QQ号的删除就搞不懂怎么组装
用这个VBS替换,目前一共有36个文件夹的内容,替换的话在10分钟内就完成了
只要转换的内容不出错,多花点时间没关系,最初的原始数据是个三列cvs,1月份到现在的数据拆分转换成现在的01-09文件夹,电脑不关机总运行了3天3夜。速度慢点没关系,只要数据转换不出错就行
作者: xczxczxcz 时间: 2021-10-5 14:47
无聊 写了个 PS 跑了下, 50秒
作者: PCL0769 时间: 2021-10-5 14:55
回复 31# xczxczxcz
老师好!
PS又是什么?
恳请老师详解,谢谢!
作者: qixiaobin0715 时间: 2021-10-5 15:36
一分钟不到解决,真乃高手也!
作者: qixiaobin0715 时间: 2021-10-5 15:48
我用纯批写了一个,且未去重,测试目录用了22分钟,一直未好意思发。
作者: newswan 时间: 2021-10-5 16:07
gnu命令: sed sort- @echo off
- setlocal ENABLEDELAYEDEXPANSION
-
- set path=%pathgnu%;%path%
- echo %path%
-
- set sour=新建文件夹
- set dest=bbb1
- set exclude=QQ
-
- del /q "%dest%\*.*"
-
- echo %~nx0 %time% 1 >>time.txt
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%sour%\*.txt"`) do (
- echo "%%~fa"
- type "%%~fa" | sed -r -e "/\S+\s+\S+\s+\S+/^!d" -e "/%exclude%/d" -e "s/SZ/1/" -e "s/SH/0/" -e "s/\s+/^|/g" >> "%dest%\%%~na.tmp"
- )
-
- echo,
- echo %~nx0 %time% 2 >>time.txt
- echo,
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%dest%\*.tmp"`) do (
- echo "%%~fa"
- type "%%~fa" | sort.exe -u >>"%%~dpna.txt"
- )
-
- echo %~nx0 %time% 3 >>time.txt
- echo,
- del %dest%\*.tmp
复制代码
作者: newswan 时间: 2021-10-5 16:08
gnu 命令 sed awk- @echo off
- setlocal ENABLEDELAYEDEXPANSION
-
- set path=%pathgnu%;%path%
- echo %path%
-
- set sour=新建文件夹
- set dest=bbb2
- set exclude=QQ
-
- del /q "%dest%\*.*"
-
- echo %~nx0 %time% 1 >>time.txt
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%sour%\*.txt"`) do (
- echo "%%~fa"
- type "%%~fa" | sed -r -e "/\S+\s+\S+\s+\S+/^!d" -e "/%exclude%/d" -e "s/SZ/1/" -e "s/SH/0/" -e "s/\s+/^|/g" >> "%dest%\%%~na.tmp"
- )
-
- echo,
- echo %~nx0 %time% 2 >>time.txt
- echo,
-
- for /f "usebackq tokens=* delims=" %%a in (`dir /s /b "%dest%\*.tmp"`) do (
- echo "%%~fa"
- type "%%~fa" | awk " { arr[$0]++ ; if ( arr[$0] == 1 ) { print $0 } } " >>"%%~dpna.txt"
- )
-
- echo %~nx0 %time% 3 >>time.txt
- echo,
- del %dest%\*.tmp
复制代码
作者: newswan 时间: 2021-10-5 16:10
效率 比较
sed + sort
1.bat 16:01:09.17 1
1.bat 16:02:06.45 2
1.bat 16:02:21.43 3
sed + awk
2.bat 16:03:13.41 1
2.bat 16:04:11.68 2
2.bat 16:04:26.42 3
两种办法 效率相同,但是 ps 就差很多了。
作者: qixiaobin0715 时间: 2021-10-5 16:16
速度够快。
作者: idwma 时间: 2021-10-5 17:24
回复 21# newswan
可以试试net静态类,这里只把读写改了就快了很多,如果把替换部分也改了应该还能再加速- Get-ChildItem -path $sour *.txt -Recurse | foreach-object {
- $_.fullname
- $b=( [IO.File]::ReadAllLines($_.fullname) ) -match "\w+\s+\w+\s+[-]?\w+" -notmatch $exclude -replace "SZ","1" -replace "SH","0" -replace "\s+","|"
- $a=$dest,$_.name -join '\'
- [IO.File]::WriteAllLines($a,$b)
- }
复制代码
作者: newswan 时间: 2021-10-5 17:33
本帖最后由 newswan 于 2021-10-5 21:07 编辑
回复 39# idwma
谢谢指点
net 没学过。。。
合并效率一样了,去重,还是很慢- $sour = "D:\share\tech\New folder\新建文件夹"
- $dest = "D:\share\tech\New folder\ccc2"
- $exclude = "QQ"
-
- Remove-Item $dest\*.*
-
- ( $MyInvocation.MyCommand.Name + " 1 " + (get-date -Format "HH:mm:ss.ff").tostring() ) | out-file -Encoding ascii -append time.txt
-
- Get-ChildItem -path $sour *.txt -Recurse | foreach-object {
- $_.fullname
- $filename = Join-Path -path $dest -ChildPath ($_.basename + ".tmp")
- $a=( [IO.File]::ReadAllLines($_.fullname) )
- $a = $a -match "\S+\s+\S+\s+\S+" -notmatch $exclude -replace "SZ","1" -replace "SH","0" -replace "\s+","|"
- [IO.File]::AppendAllLines([string]$filename , [string[]]$a)
- }
-
- ( $MyInvocation.MyCommand.Name + " 2 " + (get-date -Format "HH:mm:ss.ff").tostring() ) | out-file -Encoding ascii -append time.txt
-
- Get-ChildItem -path $dest *.tmp | foreach-object {
- $_.fullname
- $filename = Join-Path -path $dest -ChildPath ($_.basename + ".txt")
- $ht = @{}
- $a = ( [IO.File]::ReadAllLines($_.fullname) )
- $a = $a | foreach-object {
- if ( -not ( $ht.ContainsKey($_) ) )
- {
- $_
- $ht.add($_,"1")
- }
- }
- $a | out-file -Encoding utf8 $filename
- }
-
- ( $MyInvocation.MyCommand.Name + " 3 " + (get-date -Format "HH:mm:ss.ff").tostring() ) | out-file -Encoding ascii -append time.txt
复制代码
作者: PCL0769 时间: 2021-10-6 07:55
回复 31# xczxczxcz
老师好!能将这个PS发出来吗?谢谢!
作者: idwma 时间: 2021-10-6 16:16
本帖最后由 idwma 于 2021-10-6 16:17 编辑
回复 40# newswan
去重的部分抄前辈的试试看快不快http://www.bathome.net/thread-25194-2-1.html- Get-ChildItem -path $dest *.tmp | foreach-object {
- $reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $_.fullname
- $aa=New-Object System.Collections.Generic.HashSet[string]
- $_.fullname
- $filename = Join-Path -path $dest -ChildPath ($_.basename + ".txt")
- while ( $read = $reader.ReadLine() ) {
- out-null -InputObject $aa.add($read)
- }
- [IO.File]::WriteAllLines($filename,$aa)
- }
复制代码
作者: newswan 时间: 2021-10-6 20:22
回复 42# idwma
谢谢,这个用时是 unix 工具的 6 倍,比前面的要好多了
作者: newswan 时间: 2021-10-6 20:23
一段时间不用,很多都不熟悉了啊
作者: went 时间: 2021-10-6 20:26
可以尝试下多线程,线程数越多越快,取决你的cpu
数据处理函数可以自行优化- #&cls&cd /d "%~dp0" & @powershell -c "Get-Content '%~0' | Select-Object -Skip 1 | Out-String | Invoke-Expression" & pause&exit
- cls
- $t1 = Get-Date
- $src_dir = '新建文件夹'
- $dst_dir = 'out'
-
- [void][System.IO.Directory]::CreateDirectory($dst_dir)
-
- #线程函数 处理数据
- $HandleGroupJob = {
- #线程参数
- param($dst_dir,$groupInfo)
- Write-Host $groupInfo.Name
- #汇总去重并筛选
- $set = New-Object 'System.Collections.Generic.HashSet[string]'
- & { $groupInfo.Group | foreach { [IO.File]::ReadAllLines($_.FullName)} } | foreach {
- if($_ -match '\S+\s+\d+\s+-?\d{2,}'){
- [void]$set.Add(($_ -replace 'SH','1|' -replace 'SZ','0|' -replace '\s+','|'))
- }
- }
- #输出
- Out-File -InputObject $set -FilePath ('{0}\{1}' -f $dst_dir,$groupInfo.Name)
- $set = $null
- return ($groupInfo.Name + ' 已完成')
- }
-
- #多线程设置
- $pool = [runspacefactory]::CreateRunspacePool(1,10) #最多10个线程并发
- $pool.Open()
- $threads = New-Object 'System.Collections.ArrayList'
- $results = New-Object 'System.Collections.ArrayList'
-
- '开始创建线程...'
- Get-ChildItem -Recurse -Path $src_dir -Filter '*.txt' | Group-Object {$_.Name} | foreach {
- $_.Name
- $thread = [powershell]::Create()
- $thread.RunspacePool = $pool
- [void]$thread.AddScript($HandleGroupJob)
- [void]$thread.AddArgument($dst_dir)
- [void]$thread.AddArgument($_)
- [void]$threads.Add($thread)
- [void]$results.Add($thread.BeginInvoke())
- }
- '-------------------------------'
-
- '等待线程结束'
- while($true){
- $all_done = $true
- for($i = 0; $i -lt $results.Count; $i++){
- if($results[$i] -ne $null){
- if($results[$i].IsCompleted){
- $threads[$i].EndInvoke($results[$i])
- $threads[$i].Dispose()
- $threads[$i] = $null
- $results[$i] = $null
- [System.GC]::Collect()
- } else {
- $all_done = $false
- }
- }
- }
- if($all_done){ break }
- Start-Sleep -Milliseconds 500
- }
-
- #关闭线程池
- $pool.Close()
- '-------------------'
- '{0} -> {1}' -f $t1,(Get-Date)
复制代码
作者: went 时间: 2021-10-6 20:30
回复 45# went
线程不要设置过多,不然cpu容易爆满
作者: idwma 时间: 2021-10-6 20:44
回复 44# newswan
看went的代码发现一个[void],把空输出改成这个瞬间起飞呀- Get-ChildItem -path $dest *.tmp | foreach-object {
- $reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $_.fullname
- $aa=New-Object System.Collections.Generic.HashSet[string]
- $_.fullname
- $filename = Join-Path -path $dest -ChildPath ($_.basename + ".txt")
- while ( $read = $reader.ReadLine() ) {
- [void]$aa.add($read)
- }
- [IO.File]::WriteAllLines($filename,$aa)
- }
复制代码
作者: went 时间: 2021-10-6 21:01
回复 47# idwma
估计是[void]直接强转成了$null才不会输出
作者: newswan 时间: 2021-10-7 20:49
相当于复制代码
作者: WHY 时间: 2021-10-8 15:47
本帖最后由 WHY 于 2021-10-10 21:55 编辑
Test.vbs- Rem On Error Resume Next
- Dim srcDir, dstDir
-
- srcDir = "E:\Test\新建文件夹" '源文件夹路径,需替换为实际路径
- dstDir = "E:\Test\新建文件夹1" '目标文件夹路径
-
- Dim wsc
- Set wsc = CreateObject("WScript.Shell")
-
- If WSH.Arguments.Count = 0 Then
- wsc.Run "cscript " & chr(34) & WSH.ScriptFullName & chr(34) & " ARG", 0
- WScript.Quit
- End If
-
- Dim dic1, fso
- Set dic1 = CreateObject("Scripting.Dictionary")
- Set fso = CreateObject("Scripting.FileSystemObject")
-
- Dim reg
- Set reg = New RegExp
- reg.Pattern = "[ \t]+"
- reg.Global = True
-
- Dim objExec
- If Not fso.FolderExists(srcDir) Then MsgBox "源文件夹不存在" : WSH.Quit
- wsc.Run "cmd /c md " & chr(34) & dstDir & chr(34) & " 2>nul", 0 '创建目标文件夹
- Set objExec = wsc.Exec( "cmd /c dir /b /a-d /s " & chr(34) & srcDir & "\*.txt" & chr(34) ) '遍历源文件夹
-
- Rem 字典dic1,key=文件名,value=文件路径
- Dim strFilePath, strFileName
- Do Until objExec.StdOut.AtEndOfStream
- strFilePath = objExec.StdOut.ReadLine
- strFileName = fso.GetFile(strFilePath).Name
- strFileName = LCase(strFileName)
- If Not dic1.Exists(strFileName) Then
- dic1.Add strFileName, strFilePath
- Else
- dic1.Item(strFileName) = dic1.Item(strFileName) & vbLf & strFilePath
- End If
- Loop
-
- Rem 遍历字典dic1
- Dim key
- For Each key In dic1.Keys
- GetFileContent key, Split( Dic1.Item(key), vbLf )
- Next
-
- Function GetFileContent(fileName, ByRef arrFilePath)
- Dim dic2, i, objFile, strLine
- Set dic2 = CreateObject("Scripting.Dictionary")
-
- For i = 0 To UBound(arrFilePath)
- Set objFile = fso.OpenTextFile(arrFilePath(i), 1)
- Do Until objFile.AtEndOfStream
- strLine = objFile.ReadLine
- strLine = reg.Replace(strLine, "|") '空格替换为"|"
- If UBound(Split(strLine, "|")) >= 2 And InStr(strLine, "-QQ") <= 0 Then '如果大于等于3列、不含 "-QQ"
- strLine = Replace(Replace(strLine,"SZ", "0|"),"SH", "1|") '替换 "SZ" 和 "SH"
- If Not dic2.Exists(strLine) Then '字典dic2,用于去重复
- dic2.Add strLine, True
- End If
- End If
- Loop
- objFile.Close
- Set objFile = Nothing
- Next
-
- fso.OpenTextFile(dstDir & "\" & fileName, 2, True).Write( Join(dic2.Keys, vbCrLf) ) '保存
- Set dic2 = Nothing
- End Function
-
- MsgBox "Done"
复制代码
Test.PS1- $dt = get-Date;
-
- $srcDir = 'E:\Test\新建文件夹';
- $dstDir = 'E:\Test\新建文件夹1';
-
- If (![IO.Directory]::Exists($dstDir)){ $null = md $dstDir }
-
- $dic = New-Object 'System.Collections.Generic.Dictionary[string, [Collections.ArrayList]]';
-
- forEach( $file In (dir $srcDir -Recurse -Filter '*.txt') ){
- $Name = $file.BaseName.ToUpper();
- $Path = $file.FullName;
- if( !$dic.ContainsKey($Name) ){
- $dic.Add($Name, @($Path));
- } else {
- [void]$dic[$Name].Add($Path);
- }
- }
-
- forEach( $key In $dic.Keys ){
- $Hash = @{};
- for( $i=0; $i -lt $dic[$key].Count; $i++ ){
- $arr = [IO.File]::ReadAllLines($dic[$key][$i], [Text.Encoding]::Default);
- $arr = $arr -match '^(?:(?!-QQ)\S)+\s+\S+\s+\S+';
- $arr = $arr -replace '\s+', '|' -replace 'SZ', '0|' -replace 'SH', '1|';
- $Count = $arr.Count;
- for( $j=0; $j -lt $Count; $j++ ){
- if( !$Hash.ContainsKey($arr[$j]) ){
- $Hash.Add($arr[$j], $True);
- }
- }
- }
- [IO.File]::WriteAllLines( $dstDir + '\' + $key + '.txt', $Hash.Keys );
- }
- ((get-Date) - $dt).TotalSeconds;
复制代码
作者: newswan 时间: 2021-10-8 17:52
本帖最后由 newswan 于 2021-10-8 17:54 编辑
同名文件分组,流式处理
需要 sed awk sort- @echo off
- setlocal ENABLEDELAYEDEXPANSION
-
- set sour=新建文件夹
- set dest=%~n0
- set exclude=QQ
-
- set "_cmd_=dir /s /b %sour%\*.txt | sed -r -e "s/^.+[\]//" | sort -u"
- set _cmdsed_=-r -e "/%exclude%/d" -e "/^\S+\s+\S+\s+\S+$/^!d" -e "s/SZ/1/" -e "s/SH/0/" -e "s/\s+/^|/g"
- set _cmdawk_=" { arr[$0]++ ; if ( arr[$0] == 1 ) { print $0 } } "
- for /f "usebackq tokens=* delims=" %%a in (`cmd /c "%_cmd_%"`) do (
- echo %%a
- (
- for /f "usebackq tokens=* delims=" %%b in (`dir /s /b "%sour%\%%a"`) do (
- type "%%~fb"
- ) | sed -r -e $a\
- ) | sed !_cmdsed_! | awk !_cmdawk_! > "%dest%\%%~nxa"
- )
复制代码
ps: linux 的 sort 不是 windows自带的
作者: xczxczxcz 时间: 2021-10-9 11:55
原VSCODE调试50秒,
今优化了两点:I/O读取和范型数据处理,现缩短至平均24秒(23.7XX~24.2XX)。(按顶楼的要求和网盘文件)
视频被百度转码变成卡顿了
第一个视频为前台处理:约24秒
https://pan.baidu.com/s/1VXnS_n6mE457iUp-rLk8Hg
第二个视频为后台处理:约28秒
https://pan.baidu.com/s/1S6Dl1KqAus_QpBVkTcOYWw
作者: newswan 时间: 2021-10-9 12:47
本帖最后由 newswan 于 2021-10-9 12:55 编辑
回复 52# xczxczxcz
可以在vbs里加个计时器,完成后显示时长
这样时间比较准确
作者: newswan 时间: 2021-10-9 12:50
- @echo off
- setlocal ENABLEDELAYEDEXPANSION
- chcp 936
-
- set path=%pathgnu%;%path%
-
- set sour=新建文件夹
- set dest=%~n0
- set exclude=QQ
-
- if exist %dest% rd /s /q %dest%
- if not exist %dest% mkdir %dest%
-
- call :C_timer
-
- set "_cmd_=dir /s /b %sour%\*.txt | sed -r -e "s/^.+[\]//" | sort -u"
- set _cmdsed_=-r -e "/%exclude%/d" -e "/^\S+\s+\S+\s+\S+$/^!d" -e "s/SH/0/" -e "s/SZ/1/" -e "s/\s+/^|/g"
- set _cmdawk_=" { arr[$0]++ ; if ( arr[$0] == 1 ) { print $0 } } "
- for /f "usebackq tokens=* delims=" %%a in (`cmd /c "%_cmd_%"`) do (
- echo %%a
- (
- for /f "usebackq tokens=* delims=" %%b in (`dir /s /b "%sour%\%%a"`) do (
- type "%%~fb"
- ) | sed -r -e $a\
- ) | sed !_cmdsed_! | awk !_cmdawk_! > "%dest%\%%~nxa"
- )
-
- call :C_timer sum
-
- exit/b
-
- rem del %dest%\*.tmp
-
-
- :C_timer
- if not defined _ti_ set _ti_=-1
- set/a _ti_+=1
- set _tb_=%_te_%
- set _te_=%time%
- if %_ti_% EQU 0 (
- set _tb_=%_te_%
- )
- set/a _tdiff_=(9%_te_:~0,2%-9%_tb_:~0,2%)*360000+(9%_te_:~3,2%-9%_tb_:~3,2%)*6000+(9%_te_:~6,2%%_te_:~9,2%-9%_tb_:~6,2%%_tb_:~9,2%)
- set/a _tdiff_=%_tdiff_:-=8640000-%
- set/a _tdiffSum_+=%_tdiff_%
- if "%_ti_%" == "0" (
- (echo,) >>time.txt
- (echo %~nx0 %_ti_% %_te_%) >>time.txt
- ) else (
- (echo %~nx0 %_ti_% %_te_% %_tdiff_:~0,-2%.%_tdiff_:~-2%) >>time.txt
- )
- if %1.==sum. (
- (echo %~nx0 %_tdiffSum_:~0,-2%.%_tdiffSum_:~-2%) >>time.txt
- )
- goto :eof
复制代码
作者: xczxczxcz 时间: 2021-10-9 13:24
回复 54# newswan
要vbs计时器作什么, StopWatch类不香吗?
作者: newswan 时间: 2021-10-9 13:28
本帖最后由 newswan 于 2021-10-9 13:33 编辑
回复 55# xczxczxcz
我的意思是加到vbs代码里,运行完毕显示用时
MsgBox "Done 用时 xx.xx "
作者: xczxczxcz 时间: 2021-10-9 13:43
回复 56# newswan
要显示对话框的话用 VisualBasic 的对话框不更好!
作者: xczxczxcz 时间: 2021-10-9 13:45
还可以调用 winform windows的对话框,更简单
作者: xczxczxcz 时间: 2021-10-9 13:51
回复 50# WHY
看你的VBS灰常工整,灰常适合教师类工作,偶测了下时间为 1分45秒。感觉把那个字典拿掉可能会提升一些速度。字典对效率影响还是很大的。个人愚见!
作者: newswan 时间: 2021-10-9 15:33
本帖最后由 newswan 于 2021-10-9 15:34 编辑
回复 59# xczxczxcz
😓,搞错,是给 why 回复的。
没有禁用表情,怎么表情发不出
作者: newswan 时间: 2021-10-9 15:41
回复 50# WHY
可以加个计时功能,运行完成,显示用时
作者: WHY 时间: 2021-10-10 21:58
本帖最后由 WHY 于 2021-10-10 21:59 编辑
回复 59# xczxczxcz
过奖,
感谢测试。
在我的电脑上,vbs 用时 3.5 分钟,PowerShell 脚本用时 2.1 分钟
作者: PCL0769 时间: 2021-10-12 14:46
谢谢各位老师出手帮助!
作者: PCL0769 时间: 2021-10-12 16:58
回复 36# newswan
老师好!
请帮忙看看这个能用批处理完成吗?谢谢!
http://www.bathome.net/thread-60353-1-1.html
作者: PCL0769 时间: 2021-10-12 16:59
回复 45# went
老师好!
请帮忙看看这个能用批处理完成吗?谢谢!
http://www.bathome.net/thread-60353-1-1.html
作者: PCL0769 时间: 2021-10-12 17:01 标题: RE: 请老师抽空帮写一个批处理,文本合并后生成在新文件夹中去重复(已解答,谢谢!)
回复 50# WHY
老师好!
请帮忙看看这个能用批处理完成吗?谢谢!
http://www.bathome.net/thread-60353-1-1.html
作者: PCL0769 时间: 2021-10-12 17:04
回复 47# idwma
老师好!
请帮忙看看这个能用批处理完成吗?谢谢!
http://www.bathome.net/thread-60353-1-1.html
作者: PCL0769 时间: 2021-10-12 17:05
回复 52# xczxczxcz
老师好!
请帮忙看看这个能用批处理完成吗?谢谢!
http://www.bathome.net/thread-60353-1-1.html
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |