标题: [文本处理] 【已解决】求助批处理实现文本分列 [打印本页]
作者: jave000 时间: 2021-8-20 13:47 标题: 【已解决】求助批处理实现文本分列
本帖最后由 jave000 于 2021-9-10 10:13 编辑
同类搜索简述:
按创建和修改时间将一批文本文件,从一个文件夹批量复制到另一个文件夹,并且两个文件夹的路径中间都有一个变量,需要手动输入,以及其中一个路径涉及到桌面,但为了可以分享给同事使用,识别任意电脑名下的桌面路径。
同时对所有文本的内容,筛出以序号为行首的内容,并对其进行分列,再转换到csv文件,同时增加一列生成其文本文件名。
同时自动打开excel。
每一行的文本分列后,都归入独立单元格。
感谢楼下诸位
@powershell -c "Get-Content '%~0' | Select-Object -Skip 1 | Out-String | Invoke-Expression" & exit /b
$jave = read-host "Project Model Folder"
$CXMPV = [Environment]::GetFolderPath("Desktop")
$sour = "\\btssvr9\pds1\$jave\3d\su\report\"
$dest = "$CXMPV\Print\"
do
{
$minute = read-host "Minutes of Minutes"
$minute = $minute.trim()
}
while ($minute -match "\D")
Get-ChildItem -Path $sour -File *.txt |
Where-Object { ($_.CreationTime -gt (get-date).AddMinutes(-$minute)) -or ($_.LastWriteTime -gt (get-date).AddMinutes(-$minute)) } |
foreach-object {
write-host $_.fullname
copy-item $_.fullname -Destination $dest
}
Get-Item *.txt | ForEach-Object {
(Get-Content $_) -match "\s{3}\d+\s" `
-replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + "`t`$1`t`$2`t") `
-replace "\s+$","" `
-replace "\s{2,}","`t" `
-replace "(?=Baseplate)","`t" `
-replace " (?=\d+x\d+x\d+mm)","`t" `
} | Out-File z-report.csv
Remove-Item $dest*.txt
作者: Batcher 时间: 2021-8-20 14:00
回复 1# jave000
请把附件上传到阿里云盘或百度网盘
作者: jave000 时间: 2021-8-20 14:08
本帖最后由 jave000 于 2021-8-20 14:34 编辑
回复 2# Batcher
公司电脑也打不开任何网盘的网址。我晚些还是把附件发给家里电脑,晚上再传。
作者: idwma 时间: 2021-8-20 14:36
- @echo off&setlocal enabledelayedexpansion
- (for /f "delims=" %%b in ('findstr /r /c:"^ *[0-9]" "MOC922.txt"') do (
- set str=%%b
- echo;!str:~0,8!,!str:~8,8!,!str:~16,6!,!str:~22,40!,!str:~62,40!,!str:~102,16!,!str:~118!
- ))>>MOC922.txt.csv
- pause
复制代码
作者: qixiaobin0715 时间: 2021-8-20 15:11
回复 1# jave000
不用字符宽度的话,可以牵强的这么处理:- @echo off
- setlocal enabledelayedexpansion
- (for /f "tokens=*" %%i in ('findstr /br /c:" *[1-9][0-9]* " MOC922.txt') do (
- set "str1=%%i"
- set "str1=!str1: =#!"
- for /f "tokens=1-7 delims=#" %%a in ("!str1:# =#!") do echo,%%a,%%b,%%c,%%d,%%e,%%f,%%g
- ))>1.csv
- pause
复制代码
但是会带来一些问题,比如17行由于第4列为空白,就会导致后面各列依次前移。
作者: qixiaobin0715 时间: 2021-8-23 09:13
回复 3# jave000
/c:是findstr命令中的一个参数,而不是路径。参见:
http://bbs.bathome.net/thread-14682-1-1.html
作者: newswan 时间: 2021-8-23 11:48
本帖最后由 newswan 于 2021-8-23 12:46 编辑
如果列内字符串中空格不超过1个- (Get-Content -Encoding utf8 $_ | Select-String -Pattern '^\s+\d') -replace "\s{2,}",","
复制代码
作者: qixiaobin0715 时间: 2021-8-24 06:33
回复 1# jave000
cmd1152就是个极其活跃的小魔头!
作者: jave000 时间: 2021-8-24 09:19
回复 7# newswan
虽然看了书,但是"\s{2,}",","还是没看懂……
作者: qixiaobin0715 时间: 2021-8-24 09:55
回复 9# jave000
两个及两个以上的空白字符替换为英文逗号。
作者: jave000 时间: 2021-8-24 10:07
回复 10# qixiaobin0715
谢谢,懂了
作者: cmd1152 时间: 2021-8-24 10:45
回复 1# jave000
另外请cmd1152不要再在我的网盘空间刷屏了,刷了一个月,真的是怕了
.............
为什么你的名字:jave000和空间名asaman不一样?
作者: cmd1152 时间: 2021-8-24 10:46
回复 8# qixiaobin0715
我无语了呀..................
作者: jave000 时间: 2021-8-31 09:27
本帖最后由 jave000 于 2021-8-31 10:49 编辑
回复 4# idwma
谢谢,我刚发现其实有第八列remark,不过这个我自己会改了
!str:~118!是否是表达从118往后任意字符?所以不用写几个字符
我把第一个文件名改为*,可以生成,但是列宽全乱了
MOC320.t xt: 10 4 Pcs Hexagon head bolt ISO 4014 - M12x45 8.8 S t 0.276
就感觉在判定列宽时需要提前预留出文件名的名称列宽,但是不知道怎么取消txt后缀以及诡异的冒号
我又尝试了预留第一列列宽,结果后面依然是错位的,需要将实际列宽减少才大部分正确,感觉这个很奇怪
@echo off&setlocal enabledelayedexpansion
(for /f "delims=" %%i in ('findstr /br /c:" *[0-9]" "*.txt"') do (
set str=%%i
echo;!str:~0,14!,!str:~14,8!,!str:~22,8!,!str:~30,6!,!str:~36,40!,!str:~76,40!,!str:~116,16!,!str:~132,8!,!str:~140!
))>z-su.csv
作者: jave000 时间: 2021-8-31 09:53
本帖最后由 jave000 于 2021-8-31 10:56 编辑
回复 5# qixiaobin0715
谢谢,请问一下
/r /c:"^ 和 /br /c:" 是否没有区别?
“*[1-9][0-9]*”为什么可以表达个位数?我写成“[0-9]?”结果完全是空格……主要是不明白两头的星号表达什么。
并且我把idwma的“*[0-9]*”改成了“*[1-9][0-9]*”,他就不再显示个位数行了,但你的可以,很费解
第一列显示moc922.txt:而不是moc922,请问这个是哪段代码表达的?“%%a in ()”?
整体思路我看明白是把每两个空格改成#,再把“# ”替换为“#”,然后通过#来分割字段,这里好奇,是否已经能将连续的多个#认为是一个#?
发现另一个文本也有错位问题,第一行的二三列分不开,第九行的七八列分不开。能否强制使“ m”分列?
关于过长空格,能否有什么代码可以判断大于某个数量的空格可以认为是一列?
1 11.3448 m HW-Beam HW100X100 St37-1 187.379
2 14 Pcs A-Plate 16401 A-Pl16401 200x200x10 St37-1 43.960
3 1 Pcs C-Plate 12401 C-Pl12401_1 240x210x10 St37-1 3.956
4 4 Pcs Trägerklemme HCS TK St37-1 1.732
5 4 Pcs Hexagon head bolt ISO 4014 - M12x40 8.8 St 0.256
6 4 Pcs Hexagon nut ISO 4032 - M12 8.8 St 0.100
7 8 Pcs Washer ISO 7090-12 8.8 St 0.048
8 56 Pcs Duty anchor + HIT-HY150 HAS M16x125/38 5.6 St 7.000
9 0.252 m3 Baseplate Concrete 630.000 300x300x200mm
作者: jave000 时间: 2021-8-31 09:58
回复 7# newswan
谢谢,有很多样本,分列中间只有一个空格,只能按宽度了,这个分列其实比较简单,用cmd也够用了
你的这个我抄不来后面该怎么写,尝试失败
作者: newswan 时间: 2021-8-31 10:59
第四列为空,文件中有乱码- 9 0.252 m? Baseplate Concrete 630.000 300x300x200mm
复制代码
作者: qixiaobin0715 时间: 2021-8-31 11:02
两种表达方法基本一样。前面是“空格+*”,表示行首可以有若干空格或没有空格均可,[1-9]表示空格后或行首必须有1-9中数字中的1个组成,[0-9]*表示前面的数字后面可以有0到若干数字,*后面实际还有个空格。
总的意思是:匹配行首由若干空格+若干数字(至少一个)+至少一个空格组合的行,或者行首由若干数字(至少一个)+至少一个空格组合的行。
更复杂一些的可参考:
http://www.bathome.net/thread-57570-1-1.html
你的文本过于复杂,个人觉得批处理有点勉为其难。还是想想其他途径。
作者: jave000 时间: 2021-8-31 11:18
回复 18# qixiaobin0715
谢谢,按照宽度我试了很久,发现更多问题,还是你这个生成后手改更容易一些
还想请问
/br是否表示/b /r?
moc922.txt:看起来是自动生成的,能否将.txt:全部自动删除?
在for循环中,若干个连续字符,是否等同于单个该字符?(也就是说1,2和1,,,,2都一样只会分成1和2两个字段)
作者: newswan 时间: 2021-8-31 11:25
有乱码,还有空列- 1 11.3448 m HW-Beam HW100X100 St37-1 187.379
- 2 14 Pcs A-Plate 16401 A-Pl16401 200x200x10 St37-1 43.960
- 3 1 Pcs C-Plate 12401 C-Pl12401_1 240x210x10 St37-1 3.956
- 4 4 Pcs Tr鋑erklemme HCS TK St37-1 1.732
- 5 4 Pcs Hexagon head bolt ISO 4014 - M12x40 8.8 St 0.256
- 6 4 Pcs Hexagon nut ISO 4032 - M12 8.8 St 0.100
- 7 8 Pcs Washer ISO 7090-12 8.8 St 0.048
- 8 56 Pcs Duty anchor + HIT-HY150 HAS M16x125/38 5.6 St 7.000
- 9 0.252 m? Baseplate Concrete 630.000 300x300x200mm
复制代码
作者: jave000 时间: 2021-8-31 11:29
回复 20# newswan
看起来第一行二三列你分开了啊
作者: newswan 时间: 2021-8-31 11:55
本帖最后由 newswan 于 2021-8-31 14:05 编辑
如果例外情况不多,可以一个一个处理- Get-Item *.txt | ForEach-Object { (Get-Content $_) -match "\s{3}\d+\s" -replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + ",`$1,`$2,") -replace "\s{2,}","," -replace "(?=Baseplate)","," } | Out-File list
复制代码
作者: qixiaobin0715 时间: 2021-8-31 12:20
回复 19# jave000
moc922.txt:是如何产生的?把代码发上来看看。
作者: jave000 时间: 2021-8-31 12:52
回复 23# qixiaobin0715
因为我文件夹里不止一个MOC922.txt,你的代码里我把MOC922.txt改成了*.txt再运行
若干个txt生成结果就是额外自动生成了第一列
作者: qixiaobin0715 时间: 2021-8-31 13:28
回复 24# jave000
你是想保留文件名还是不保留?
如果要保留是和序号在一列还是单独一列?
作者: qixiaobin0715 时间: 2021-8-31 13:32
回复 15# jave000
代码默认两个以上空格分为一列。
作者: qixiaobin0715 时间: 2021-8-31 13:41
第一行的二三列分不开,第九行的七八列分不开
是因为它们之间只有一个空格,代码就识别不了,电脑不是人脑,识别不了。
作者: jave000 时间: 2021-8-31 15:58
回复 25# qixiaobin0715
要保留的,单独一列。
所有文件都是一样的,只要第一步将“ m”改为“ m”,“0 3”改为“0 3”就行,然后继续双空格替换为“#”,”# “替换为“#”,这些我大概会改。
就是好奇为什么不需要将若干个连续的“#*”替换为“#”?
作者: Batcher 时间: 2021-8-31 16:12
回复 19# jave000
是的,有些命令的参数必须分开写,有些命令的参数可以合在一起。我个人倾向于分开写。
作者: jave000 时间: 2021-8-31 17:02
本帖最后由 jave000 于 2021-8-31 17:12 编辑
回复 22# newswan
@powershell -c "Get-Content '%~0' | Select-Object -Skip 1 | Out-String | Invoke-Expression" & exit /b
$jave = read-host "Project Model Folder"
$CXMPV = [Environment]::GetFolderPath("Desktop")
$sour = "\\btssvr9\pds1\$jave\3d\su\report"
$dest = "$CXMPV\Print"
do
{
$minute = read-host "Minutes of Minutes"
$minute = $minute.trim()
}
while ($minute -match "\D")
Get-ChildItem -Path $sour -File |
Where-Object { ($_.CreationTime -gt (get-date).AddMinutes(-$minute)) -or ($_.LastWriteTime -gt (get-date).AddMinutes(-$minute)) } |
foreach-object {
write-host $_.fullname
copy-item $_.fullname -Destination $dest
}
Get-Item *.txt | ForEach-Object { (Get-Content $_) -match "\s{3}\d+\s" -replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + ",`$1,`$2,") -replace "\s{2,}","," -replace "Baseplate",",Baseplate" } | Out-File z-su.csv
Invoke-Item $sour
尝试了一下,我们服务器网盘的文件无法直接处理,只能先复制过来,再处理,但是powershell删除$dest目录下所有txt是什么句式我还不知道
另外我转成csv或txt,都没有自动分列,都在同一列,remarks分列我可以自己想想
这个环视替换挺有用,cmd要是也能用就好了
也想着把时间判定删掉,只保留以下,但是运行失败了
Get-ChildItem -Path $sour -File |
foreach-object {
write-host $_.fullname
copy-item $_.fullname -Destination $dest
作者: qixiaobin0715 时间: 2021-8-31 18:11
回复 28# jave000
将下列代码放在5楼4-5行之间:- set "str1=!str: m = m !"
- set "str1=!str:0 3=0 3!"
复制代码
但我总觉得这样改有点牵强,也会有问题。先试试吧。
作者: qixiaobin0715 时间: 2021-8-31 18:20
回复 24# jave000
MOC922.txt改成了*.txt运行的话,增加一行代码:- set "str1=!str1:.txt:=,!"
复制代码
作者: newswan 时间: 2021-8-31 18:42
回复 30# jave000
csv 要求,如果有空格,必须用""
作者: newswan 时间: 2021-8-31 18:57
本帖最后由 newswan 于 2021-8-31 19:43 编辑
- Get-Item *.txt | ForEach-Object {
- (Get-Content $_) -match "\s{3}\d+\s" `
- -replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + ",`$1,`$2,") `
- -replace "\s+$","" `
- -replace "\s{2,}","," `
- -replace "(?=Baseplate)","," `
- } | Out-File list
复制代码
作者: qixiaobin0715 时间: 2021-8-31 19:19
回复 33# newswan
好像你记错了,列内有英文逗号,整列要加双引号;列内有双引号的,双引号字符要连续写两次,且整列再加双引号。
作者: newswan 时间: 2021-8-31 19:35
回复 35# qixiaobin0715
看了一下,好像空格不必 ""
作者: newswan 时间: 2021-8-31 19:52
本帖最后由 newswan 于 2021-8-31 23:40 编辑
现在没有 office 不好测试,csv 的规范 有些不一致
ms office 默认tab
不知道要不要求标题,字段数量
作者: newswan 时间: 2021-8-31 23:40
- Get-Item *.txt | ForEach-Object {
- (Get-Content $_) -match "\s{3}\d+\s" `
- -replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + "`t`$1`t`$2`t") `
- -replace "\s+$","" `
- -replace "\s{2,}","`t" `
- -replace "(?=Baseplate)","`t" `
- } | Out-File list.csv
复制代码
作者: jave000 时间: 2021-9-1 09:10
本帖最后由 jave000 于 2021-9-1 09:12 编辑
回复 38# newswan
Remove-Item -Path $dest * -Include .txt
Remove-Item -Path $dest\ * -Include .txt
Remove-Item -Path $dest\* -Include .txt
Remove-Item -Path $dest -Include *.txt
Remove-Item -Path $dest *.txt
Remove-Item -Path $dest\*.txt
我试了如上的代码,全都无法删除txt,请问是为什么?
所以`t表示分列符号喽,你prt代码我又多看懂一点
作者: jave000 时间: 2021-9-1 09:38
回复 38# newswan
目前写成这样,就完美使用了,只有最后一句删除的代码怎么改也无法成功。
@powershell -c "Get-Content '%~0' | Select-Object -Skip 1 | Out-String | Invoke-Expression" & exit /b
$jave = read-host "Project Model Folder"
$CXMPV = [Environment]::GetFolderPath("Desktop")
$sour = "\\btssvr9\pds1\$jave\3d\su\report\"
$dest = "$CXMPV\Print\"
do
{
$minute = read-host "Minutes of Minutes"
$minute = $minute.trim()
}
while ($minute -match "\D")
Get-ChildItem -Path $sour -File |
Where-Object { ($_.CreationTime -gt (get-date).AddMinutes(-$minute)) -or ($_.LastWriteTime -gt (get-date).AddMinutes(-$minute)) } |
foreach-object {
write-host $_.fullname
copy-item $_.fullname -Destination $dest
}
Get-Item *.txt | ForEach-Object {
(Get-Content $_) -match "\s{3}\d+\s" `
-replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + "`t`$1`t`$2`t") `
-replace "\s+$","" `
-replace "\s{2,}","`t" `
-replace "(?=Baseplate)","`t" `
-replace " (?=\d+x\d+x\d+mm)","`t" `
} | Out-File z-su.csv
Invoke-Item -Path $sour
Remove-Item -Path $dest -File *.txt
作者: jave000 时间: 2021-9-1 10:09
回复 31# qixiaobin0715
这几天正在学习for、set、if,现在印象更深了,谢谢
作者: newswan 时间: 2021-9-1 16:05
https://docs.microsoft.com/en-us ... agement/remove-item[/url]
作者: jave000 时间: 2021-9-1 22:49
本帖最后由 jave000 于 2021-9-2 12:46 编辑
回复 42# newswan
失败
Remove-Item -Path $dest * -Include *.txt
成功
Remove-Item -Path $dest* -Include *.txt
Remove-Item -Path $dest*.txt
Remove-Item $dest*.txt
另外Get-Item和Get-childItem的区别是后者包括指定路径下的子目录么?
但我目前用的功能都是指定路径根目录下,结果改了你的一个Get-childItem成为Get-Item却无法运行了,很费解
作者: newswan 时间: 2021-9-2 21:13
回复 43# jave000
可以多一个 \ 比较清晰- $dest = "D:\"
- Test-Path $dest\1
复制代码
作者: jave000 时间: 2021-9-3 23:11
回复 44# newswan
所以代码里前面带\,后面还带\,路径中一个\和两个\是等价的?
这样挺好的,$dest*.txt还好,如果说$destabc.txt,真的怀疑程序能否识别了
作者: jave000 时间: 2021-9-9 22:17
回复 46# qixiaobin0715
没删,我是把个性化需求改写成通用范例的描述
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |