Board logo

标题: [文本处理] 【已解决】求助批处理实现文本分列 [打印本页]

作者: 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

  1. @echo off&setlocal enabledelayedexpansion
  2. (for /f "delims=" %%b in ('findstr /r /c:"^ *[0-9]" "MOC922.txt"') do (
  3. set str=%%b
  4. echo;!str:~0,8!,!str:~8,8!,!str:~16,6!,!str:~22,40!,!str:~62,40!,!str:~102,16!,!str:~118!
  5. ))>>MOC922.txt.csv
  6. pause
复制代码

作者: qixiaobin0715    时间: 2021-8-20 15:11

回复 1# jave000
不用字符宽度的话,可以牵强的这么处理:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "tokens=*" %%i in ('findstr /br /c:" *[1-9][0-9]* " MOC922.txt') do (
  4.     set "str1=%%i"
  5.     set "str1=!str1:  =#!"
  6.     for /f "tokens=1-7 delims=#" %%a in ("!str1:# =#!") do echo,%%a,%%b,%%c,%%d,%%e,%%f,%%g
  7. ))>1.csv
  8. 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个
  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不要再在我的网盘空间刷屏了,刷了一个月,真的是怕了

    .............
   
附件在http://asaman.ys168.com/

    为什么你的名字:jave000和空间名asaman不一样?
作者: cmd1152    时间: 2021-8-24 10:46

回复 8# qixiaobin0715


   
cmd1152就是个极其活跃的小魔头!

    我无语了呀..................
作者: 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

第四列为空,文件中有乱码
  1.    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.    1    11.3448 m     HW-Beam                                 HW100X100                               St37-1         187.379                              
  2.    2    14      Pcs   A-Plate 16401                           A-Pl16401 200x200x10                    St37-1          43.960                              
  3.    3    1       Pcs   C-Plate 12401                           C-Pl12401_1 240x210x10                  St37-1           3.956                              
  4.    4    4       Pcs   Tr鋑erklemme                            HCS TK                                  St37-1           1.732                              
  5.    5    4       Pcs   Hexagon head bolt                       ISO 4014 - M12x40                       8.8 St           0.256                              
  6.    6    4       Pcs   Hexagon nut                             ISO 4032 - M12                          8.8 St           0.100                              
  7.    7    8       Pcs   Washer                                  ISO 7090-12                             8.8 St           0.048                              
  8.    8    56      Pcs   Duty anchor + HIT-HY150                 HAS M16x125/38                          5.6 St           7.000                              
  9.    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 编辑

如果例外情况不多,可以一个一个处理
  1. 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


/br是否表示/b /r?

是的,有些命令的参数必须分开写,有些命令的参数可以合在一起。我个人倾向于分开写。
作者: 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行之间:
  1. set "str1=!str: m =  m !"
  2. set "str1=!str:0 3=0  3!"
复制代码
但我总觉得这样改有点牵强,也会有问题。先试试吧。
作者: qixiaobin0715    时间: 2021-8-31 18:20

回复 24# jave000
MOC922.txt改成了*.txt运行的话,增加一行代码:
  1. 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 编辑
  1. Get-Item *.txt | ForEach-Object {
  2.     (Get-Content $_) -match "\s{3}\d+\s" `
  3.         -replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + ",`$1,`$2,") `
  4.         -replace "\s+$","" `
  5.         -replace "\s{2,}","," `
  6.         -replace "(?=Baseplate)","," `
  7. } | 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

  1. Get-Item *.txt | ForEach-Object {
  2.     (Get-Content $_) -match "\s{3}\d+\s" `
  3.         -replace "^\s+(\d+)\s+([\d.]+)\s+",($_.BaseName + "`t`$1`t`$2`t") `
  4.         -replace "\s+$","" `
  5.         -replace "\s{2,}","`t" `
  6.         -replace "(?=Baseplate)","`t" `
  7. } | 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

可以多一个 \ 比较清晰
  1. $dest = "D:\"
  2. 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