Board logo

标题: [文本处理] 批处理怎样按条件插入行填补行? [打印本页]

作者: 娜美    时间: 2023-8-19 22:16     标题: 批处理怎样按条件插入行填补行?

本帖最后由 娜美 于 2023-8-20 14:04 编辑

补充一些a文本
  1. a.txt  ANSI编码
  2. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  3. 19:37:31 August 16 2023>   ++++
  4. 19:37:32 August 16 2023>   企业 名称:利海 B
  5. 19:37:33 August 16 2023>    +
  6. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  7. 19:37:35 August 16 2023>   +
  8. 19:37:36 August 16 2023>   企业 名称:海
  9. 19:37:39 August 16 2023>   退出
  10. 20:37:30 August 16 2023>   企业 名称:利海 B
  11. 20:39:30 August 16 2023>   企业 名称:利海 B
  12. 20:38:31 August 16 2023>   退出
  13. 20:37:30 August 16 2023>   企业 名称:利
  14. 20:39:30 August 16 2023>   +
  15. 20:39:30 August 16 2023>   +
  16. 20:39:30 August 16 2023>   +
  17. 20:39:30 August 16 2023>   退出
  18. 20:39:30 August 16 2023>   企业 名称:利海 B
  19. 20:38:31 August 16 2023>   退出
  20. 企业"字段 至 "企业"字段 之间 或许会有很多行,  示例中只是尽量缩短没影响的行
  21. if 如果遇到有"企业"字段 与 "企业"字段 之间的名称不相同,  且它们中间没有 "退出"字段, 则需要添加插入 "退出"字段行,  如果他们字段之间有了 "退出"字段, 则跳过忽略,  日期时间填补请使用有"企业"字段的上一行日期时间
  22. if 如果有"企业"字段的行  一直至有 "退出"字段行中, 它们名称仍然都是相同的,  ,  则不做任何动作
  23. 名称有可能会使用某些字符号,    希望可尽量支持多些名称字符
  24. PowerShell  awk bat
  25. 或许 可以将 ">"  看成分隔符处理吧
  26. >b.txt
  27. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  28. 19:37:31 August 16 2023>   ++++
  29. 19:37:31 August 16 2023>   退出
  30. 19:37:32 August 16 2023>   企业 名称:利海 B
  31. 19:37:33 August 16 2023>    +
  32. 19:37:33 August 16 2023>    退出
  33. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  34. 19:37:35 August 16 2023>   +
  35. 19:37:35 August 16 2023>   退出
  36. 19:37:36 August 16 2023>   企业 名称:海
  37. 19:37:39 August 16 2023>   退出
  38. 20:37:30 August 16 2023>   企业 名称:利海 B
  39. 20:39:30 August 16 2023>   企业 名称:利海 B
  40. 20:38:31 August 16 2023>   退出
  41. 20:37:30 August 16 2023>   企业 名称:利
  42. 20:39:30 August 16 2023>   +
  43. 20:39:30 August 16 2023>   +
  44. 20:39:30 August 16 2023>   +
  45. 20:39:30 August 16 2023>   退出
  46. 20:39:30 August 16 2023>   企业 名称:利海 B
  47. 20:38:31 August 16 2023>   退出
复制代码

作者: 77七    时间: 2023-8-19 23:08

a.txt
  1. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  2. 19:37:32 August 16 2023>   企业 名称:利海 B
  3. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  4. 19:37:36 August 16 2023>   企业 名称:利海 B
  5. 19:37:39 August 16 2023>   退出
  6. 20:37:30 August 16 2023>   企业 名称:利海 B
  7. 20:39:30 August 16 2023>   企业 名称:利海 B
  8. 20:38:31 August 16 2023>   退出
复制代码


执行
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "useback tokens=1* delims=:" %%f in (`findstr /n .* "a.txt"`) do (
  4. for /f "tokens=1* delims=>" %%a in ("%%g") do (
  5. if defined name (
  6. if "!name!" neq "%%b" (
  7. if "%%b" neq "   退出 " (
  8. echo !t!^>   退出
  9. set name=%%b
  10. ) else set name=
  11. )
  12. ) else set name=%%b
  13. set t=%%a
  14. )
  15. echo=%%g
  16. ))>b.txt
  17. endlocal
  18. pause
复制代码


b.txt
  1. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  2. 19:37:30 August 16 2023>   退出
  3. 19:37:32 August 16 2023>   企业 名称:利海 B
  4. 19:37:32 August 16 2023>   退出
  5. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  6. 19:37:34 August 16 2023>   退出
  7. 19:37:36 August 16 2023>   企业 名称:利海 B
  8. 19:37:39 August 16 2023>   退出
  9. 20:37:30 August 16 2023>   企业 名称:利海 B
  10. 20:39:30 August 16 2023>   企业 名称:利海 B
  11. 20:38:31 August 16 2023>   退出
复制代码

作者: 娜美    时间: 2023-8-19 23:29

本帖最后由 娜美 于 2023-8-19 23:42 编辑

回复 2# 77七

字段与字段之间行数不固定哦,  字段与字段之间 没有"退出" 补一行就行,  似乎补多了
  1. 如果中间行数多几行情况
  2. a.txt
  3. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  4. 19:37:31 August 16 2023>   ++++
  5. 19:37:31 August 16 2023> ++++
  6. 19:37:31 August 16 2023> ++++
  7. 19:37:32 August 16 2023>   企业 名称:利海 B
  8. 19:37:33 August 16 2023>    +
  9. 如果"企业" 与 "企业"字段之间没有"退出" 字段,  在有"企业"字段上一行添加一行就行,   似乎在企业下面也添加了,   重复添加了
  10. >b.txt
  11. 19:37:30 August 16 2023> 企业 名称:优 美 利 A
  12. 19:37:30 August 16 2023>   退出
  13. 19:37:31 August 16 2023> ++++
  14. 19:37:31 August 16 2023> ++++
  15. 19:37:31 August 16 2023> ++++
  16. 19:37:31 August 16 2023>   退出
  17. 19:37:32 August 16 2023> 企业 名称:利海 B
  18. 19:37:32 August 16 2023>   退出
  19. 19:37:33 August 16 2023> +
复制代码

作者: 77七    时间: 2023-8-19 23:46

回复 3# 娜美


   提供的样本需要保持原样,我用2楼中a.txt测试没问题。请提供一个测试出现问题的样本,看看问题出现在哪里。
作者: 娜美    时间: 2023-8-19 23:50

本帖最后由 娜美 于 2023-8-20 00:00 编辑

回复 4# 77七

好的
   例如这样的样例
  1. a.txt
  2. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  3. 19:37:31 August 16 2023>   ++++
  4. 19:37:31 August 16 2023>   ++++
  5. 19:37:31 August 16 2023>   ++++
  6. 19:37:31 August 16 2023>   ++++
  7. 19:37:31 August 16 2023>   ++++
  8. 19:37:32 August 16 2023>   企业 名称:利海 B
  9. 19:37:33 August 16 2023>    +
  10. 19:37:33 August 16 2023>    +
  11. 19:37:33 August 16 2023>    +
  12. 19:37:33 August 16 2023>    +
  13. 19:37:33 August 16 2023>    +
  14. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  15. 19:37:35 August 16 2023>   +
  16. 19:37:35 August 16 2023>   +
  17. 19:37:35 August 16 2023>   +
  18. 19:37:35 August 16 2023>   +
  19. 19:37:35 August 16 2023>   +
  20. 19:37:36 August 16 2023>   企业 名称:利海 B
  21. 20:37:30 August 16 2023>   +
  22. 20:37:30 August 16 2023>   +
  23. 20:37:30 August 16 2023>   企业 名称:利海 B
  24. 20:39:30 August 16 2023>   +
  25. 20:39:30 August 16 2023>   +
  26. 20:39:30 August 16 2023>   +
  27. 20:39:30 August 16 2023>   企业 名称:利海 B
  28. 20:38:31 August 16 2023>   退出
  29. >b.txt
  30. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  31. 19:37:31 August 16 2023>   ++++
  32. 19:37:31 August 16 2023>   ++++
  33. 19:37:31 August 16 2023>   ++++
  34. 19:37:31 August 16 2023>   ++++
  35. 19:37:31 August 16 2023>   ++++
  36. 19:37:31 August 16 2023>   退出
  37. 19:37:32 August 16 2023>   企业 名称:利海 B
  38. 19:37:33 August 16 2023>    +
  39. 19:37:33 August 16 2023>    +
  40. 19:37:33 August 16 2023>    +
  41. 19:37:33 August 16 2023>    +
  42. 19:37:33 August 16 2023>    +
  43. 19:37:33 August 16 2023>    退出
  44. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  45. 19:37:35 August 16 2023>   +
  46. 19:37:35 August 16 2023>   +
  47. 19:37:35 August 16 2023>   +
  48. 19:37:35 August 16 2023>   +
  49. 19:37:35 August 16 2023>   +
  50. 19:37:35 August 16 2023>   退出
  51. 19:37:36 August 16 2023>   企业 名称:利海 B
  52. 20:37:30 August 16 2023>   +
  53. 20:37:30 August 16 2023>   +
  54. 20:37:30 August 16 2023>   企业 名称:利海 B
  55. 20:39:30 August 16 2023>   +
  56. 20:39:30 August 16 2023>   +
  57. 20:39:30 August 16 2023>   +
  58. 20:39:30 August 16 2023>   企业 名称:利海 B
  59. 20:38:31 August 16 2023>   退出
复制代码

作者: 77七    时间: 2023-8-20 00:01

本帖最后由 77七 于 2023-8-20 00:08 编辑

回复 5# 娜美


  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "useback tokens=1* delims=:" %%f in (`findstr /n .* "a.txt"`) do (
  4. set str=%%g
  5. set str1=!str:企业=!
  6. if "!str1:退出=!" neq "!str!" (
  7. for /f "tokens=1* delims=>" %%a in ("%%g") do (
  8. if defined name (
  9. if "!name!" neq "%%b" (
  10. if "%%b" neq "   退出 " (
  11. echo !t!^>   退出
  12. set name=%%b
  13. ) else set name=
  14. )
  15. ) else set name=%%b
  16. set t=%%a
  17. )
  18. )
  19. echo=%%g
  20. ))>b.txt
  21. endlocal
  22. pause
复制代码

作者: 娜美    时间: 2023-8-20 00:17

本帖最后由 娜美 于 2023-8-20 00:24 编辑

回复 6# 77七


   这次基本对了,   不过补的时间不是上一行时间,  只是时间补错了  会寻致下一步不能正确计算时间        请帮忙再看下
作者: 77七    时间: 2023-8-20 00:23

回复 7# 娜美


  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "useback tokens=1* delims=:" %%f in (`findstr /n .* "a.txt"`) do (
  4. set str=%%g
  5. set str1=!str:企业=!
  6. if "!str1:退出=!" neq "!str!" (
  7. for /f "tokens=1* delims=>" %%a in ("%%g") do (
  8. if defined name (
  9. if "!name!" neq "%%b" (
  10. if "%%b" neq "   退出 " (
  11. echo !t!^>   退出
  12. set name=%%b
  13. ) else set name=
  14. )
  15. ) else set name=%%b
  16. )
  17. )
  18. for /f "tokens=1* delims=>" %%a in ("%%g") do (
  19. set t=%%a
  20. )
  21. echo=%%g
  22. ))>b.txt
  23. endlocal
  24. pause
复制代码
修改时忘记考虑了。
作者: 娜美    时间: 2023-8-20 00:28

回复 8# 77七


   多谢哥哥基本正确了,   晚安       我明天再细试一下     
    哥哥晚安
作者: Nsqs    时间: 2023-8-20 05:33

本帖最后由 Nsqs 于 2023-8-20 07:48 编辑

ps没那么复杂
  1. $data=gc a.txt
  2. $s=New-Object 'System.Collections.Generic.List[string][]' 3
  3. $f='企业'
  4. for($i=0;$i -lt $data.Count;$i++){
  5.     if($data[$i] -match $f){
  6.         [int]$c=$c%2+1
  7.         $s[$c]=[regex]::Matches($data[$i],"$f.+")
  8.         if($s[1] -ne $s[2]){
  9.             $b=$data[$i-1]
  10.             $data[$i-1]="$($b)`r`n$([regex]::Matches($b,'.+>'))   退出"
  11.         }
  12.     }
  13. }
  14. $data=$data -split '\r\n'
  15. $data[0..($data.Count-2)]>b.txt
复制代码
bat
  1. @echo off&setlocal enabledelayedexpansion
  2. set n=100
  3. for /f "delims=" %%1 in (a.txt)do set /a n+=1&call set "#%%n%%=%%1"
  4. for /f "tokens=1,2,6* delims=#= " %%1 in ('set #')do (
  5. set /a a=%%1
  6. set "line=%%3%%4%%5"
  7. set d=!line:*   =!
  8. set d=!d:~,2!
  9. if !d!==企业 (
  10. call set "s!c!=!line!"
  11. set /a c=c %% 2+1
  12. if !s1! neq !s2! (
  13. set /a b=a-1
  14. call set "#!b!#=%%#!b!:+=%%退出"
  15. )))
  16. (for /f "tokens=2* delims==" %%1 in ('set #')do echo %%1)>b1.txt
复制代码

作者: 娜美    时间: 2023-8-20 08:17

本帖最后由 娜美 于 2023-8-20 09:06 编辑

回复 10# Nsqs


   PS 较为理想,  但是在实际文本中会在第一行产生多余的一行 "   退出 "   其他的还产生重复插入字段情况
例如, 以下这种情况在样式例子中不会,  但在实际文本中会发生如下情况,  多了一行
  1. a.txt
  2. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  3. 19:37:31 August 16 2023>   ++++
  4. 19:37:31 August 16 2023>   ++++
  5. 19:37:31 August 16 2023>   ++++
  6. 19:37:31 August 16 2023>   ++++
  7. 19:37:31 August 16 2023>   ++++
  8. 19:37:31 August 16 2023>   退出
  9. 19:37:32 August 16 2023>   企业 名称:海
  10. 像这种已存在条件情况,  也会重复插入了
  11. >b.txt
  12. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  13. 19:37:31 August 16 2023>   ++++
  14. 19:37:31 August 16 2023>   ++++
  15. 19:37:31 August 16 2023>   ++++
  16. 19:37:31 August 16 2023>   ++++
  17. 19:37:31 August 16 2023>   ++++
  18. 19:37:31 August 16 2023>   退出
  19. 19:37:31 August 16 2023>   退出
  20. 19:37:32 August 16 2023>   企业 名称:海
复制代码
最好能在完成后记录可以显示在那些行号插入字段变动
例如: 10,115,119,212行
作者: 娜美    时间: 2023-8-20 09:09

本帖最后由 娜美 于 2023-8-20 09:18 编辑

回复 8# 77七


    试了100mb文件,  似乎好慢,  不知道还能加快不
最好能在完成后记录可以显示在那些行号插入字段变动
例如: 10,115,119,212行
作者: qixiaobin0715    时间: 2023-8-20 10:03

最好把实际数据的片段贴出来。感觉先用时间判断,再用“企业”和“退出”多重判断效率较高。
作者: 娜美    时间: 2023-8-20 10:21

本帖最后由 娜美 于 2023-8-20 10:30 编辑

回复 13# qixiaobin0715

实际数据就是5楼加上11楼数据,,, 只不过1楼举例没有足够的多, 在5楼,   11楼添加另外情况,  事实上都差不多

主要这2个条件判断呗,    耍检查有"企业"字段 与 "企业"字段 之间的名称是否相同, 其中是否存在有 "退出"字段的行
   
  1. a.txt  ANSI编码
  2. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  3. 19:37:31 August 16 2023>   ++++
  4. 19:37:32 August 16 2023>   企业 名称:利海 B
  5. 19:37:33 August 16 2023>    +
  6. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  7. 19:37:35 August 16 2023>   +
  8. 19:37:36 August 16 2023>   企业 名称:利海 B
  9. 19:37:39 August 16 2023>   退出
  10. 20:37:30 August 16 2023>   企业 名称:利海 B
  11. 20:39:30 August 16 2023>   企业 名称:利海 B
  12. 20:38:31 August 16 2023>   退出
  13. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  14. 19:37:31 August 16 2023>   ++++
  15. 19:37:31 August 16 2023>   ++++
  16. 19:37:31 August 16 2023>   ++++
  17. 19:37:31 August 16 2023>   ++++
  18. 19:37:31 August 16 2023>   ++++
  19. 19:37:32 August 16 2023>   企业 名称:利海 B
  20. 19:37:33 August 16 2023>    +
  21. 19:37:33 August 16 2023>    +
  22. 19:37:33 August 16 2023>    +
  23. 19:37:33 August 16 2023>    +
  24. 19:37:33 August 16 2023>    +
  25. 19:37:34 August 16 2023>   企业 名称:利海 01:C (A)
  26. 19:37:35 August 16 2023>   +
  27. 19:37:35 August 16 2023>   +
  28. 19:37:35 August 16 2023>   +
  29. 19:37:35 August 16 2023>   +
  30. 19:37:35 August 16 2023>   +
  31. 19:37:36 August 16 2023>   企业 名称:利海 B
  32. 20:37:30 August 16 2023>   +
  33. 20:37:30 August 16 2023>   +
  34. 20:37:30 August 16 2023>   企业 名称:利海 B
  35. 20:39:30 August 16 2023>   +
  36. 20:39:30 August 16 2023>   +
  37. 20:39:30 August 16 2023>   +
  38. 20:39:30 August 16 2023>   企业 名称:利海 B
  39. 20:38:31 August 16 2023>   退出
  40. 19:37:30 August 16 2023>   企业 名称:优 美 利 A
  41. 19:37:31 August 16 2023>   ++++
  42. 19:37:31 August 16 2023>   ++++
  43. 19:37:31 August 16 2023>   ++++
  44. 19:37:31 August 16 2023>   ++++
  45. 19:37:31 August 16 2023>   ++++
  46. 19:37:31 August 16 2023>   退出
  47. 19:37:32 August 16 2023>   企业 名称:海
复制代码

作者: 77七    时间: 2023-8-20 11:40

本帖最后由 77七 于 2023-8-21 13:01 编辑

回复 12# 娜美


  
echo a                        0.41毫秒
echo a>>b.txt,       0.30毫秒
echo. a>>b.txt      1,30毫秒  (不知为什么这一点会多用那么多时间)
findstr “aa” a.txt    44.90毫秒
type a.txt |findstr “aa”   99.12毫秒
for /f %%a in (‘set #’) do (rem),  42.70毫秒
探讨批处理代码效率

说法有误 :文本太大,以500万行算,只echo %%a就需要半小时,echo=%%a,需要更久。而且一个for /f 可能需要2毫秒,乘以500万,又是几个小时。
考虑其它脚本吧。
作者: 娜美    时间: 2023-8-20 13:11

回复 15# 77七


   10楼PowerShell码 基本符合, 但就是会重复多添加一行 "退出"字段
作者: 娜美    时间: 2023-8-20 14:00

回复 10# Nsqs


    找到 10楼PowerShell码 问题所在了
    如果"企业" 上下 字段名称不相同  其中间也含有退出字段情况,   他仍然会重复多添加一行 "退出" 字段,,  

他们之间已有了"退出" 字段行,  这种情况下应该跳过不做任何动作
作者: Five66    时间: 2023-8-20 15:01

脑子不灵活的我只能用最原始的方式弄出来,powershell代码
  1. $inf="a.txt"
  2. $otf="b.txt"
  3. $r='企业\s*名称.+|退出'
  4. $inf=[io.file]::ReadAllLines($pwd.path+"\$inf",[text.encoding]::Default)
  5. if(!$inf){exit}
  6. $n=0
  7. $f=[System.IO.StringWriter]::new()
  8. for($i=0;$i -lt $inf.Length;$i++){
  9. if(!$inf[$i]){$f.WriteLine();continue}
  10. if($n -and $n[1]){
  11. $m=[regex]::Match($inf[$i],"$r")
  12. if($m.success -and ($m.value -eq "退出")){$f.WriteLine($inf[$i]);$n=0;continue}
  13. #if($m.success -and ($m.value.split(':')[1] -eq $n.split(':')[1])){$f.WriteLine($inf[$i]);$n=0;continue}
  14. if($m.success -and ($m.value -eq $n[1])){$f.WriteLine($inf[$i]);$n[0]=$i;continue}
  15. if($m.success){
  16. $z=[regex]::Match($inf[$n[0]],">\s*")
  17. echo "从原文本第 $i 行后插入"
  18. $f.WriteLine($inf[$n[0]].substring(0,$z.index+$z.length)+"退出");
  19. $f.WriteLine($inf[$i])
  20. $n=@($i,$m.value);continue}
  21. $f.WriteLine($inf[$i]);$n[0]=$i;continue
  22. }
  23. $m=[regex]::Match($inf[$i],"$r")
  24. if($m.success -and ($m.value -ne "退出")){$n=@($i,$m.value)}
  25. $f.WriteLine($inf[$i])
  26. }
  27. if($n){
  28. $z=[regex]::Match($inf[$n[0]],">\s*")
  29. echo "从原文本末尾插入"
  30. $f.WriteLine($inf[$n[0]].substring(0,$z.index+$z.length)+"退出");
  31. }
  32. [io.file]::WriteAllText($pwd.path+"\$otf",$f.ToString(),[text.encoding]::default)
  33. pause;$f.Dispose()
复制代码

作者: 娜美    时间: 2023-8-20 15:47

回复 18# Five66


   完全正确, 谢谢哥哥
作者: Nsqs    时间: 2023-8-20 18:09

本帖最后由 Nsqs 于 2023-8-20 18:59 编辑
  1. $data=gc a.txt
  2. $s=New-Object 'System.Collections.Generic.List[string][]' 3
  3. $f='企业'
  4. [string[]]$x=@{}
  5. @(for($i=0;$i -lt $data.Count;$i++){
  6.     $x+=$data[$i]
  7.     if($data[$i] -match $f){
  8.         [int]$c=$c%2+1
  9.         $s[$c]=[regex]::Matches($data[$i],"$f.+")
  10.         if($s[1] -ne $s[2] -and $x -notmatch '退出'){
  11.             $b=$data[$i-1]
  12.             if($i -gt 1){[PSCustomObject]@{'Changed'="Source:`t$("$i".PadLeft(4))";Source=$($data[$i-1])}}
  13.             $r="$([regex]::Matches($b,'.+>'))   退出"
  14.             $data[$i-1]="$($b)`r`n$r"
  15.             if($i -gt 1){[PSCustomObject]@{'Changed'="New`t$("$($i+1)".PadLeft(4))";Source=$r}}
  16.         }
  17.         $x=@{}
  18.     }
  19. })|ft -Wrap -AutoSize
  20. $data=$data -split '\r\n'
  21. $data[0..($data.Count-2)]>b.txt
  22. cmd /c pause
复制代码
不知道是不是这样呢?
作者: hfxiang    时间: 2023-8-20 20:39

回复 1# 娜美
用awk可以实现:
  1. awk -F"企业 名称:" "/^[ t]+$/{next}{C=$0}/企业 名称:/{A=B;B=$2;if(A!=B)C=\"\n\"C}/退出/{C=C\"\n\"}{print C}" a.txt|awk -F"[\n>]+" -vRS="" "/^[ t]+$/{next}/退出/{print $0 \"\n\";next}{print $0\"\n\"$(NF-1)\"^>   退出 \n\"}">b.txt
复制代码

作者: qixiaobin0715    时间: 2023-8-21 09:20

本帖最后由 qixiaobin0715 于 2023-8-23 11:36 编辑

由于审题不仔细,代码思路不对,此贴作废。
回复 14# 娜美
总感觉你提供的文本哪里有不规范的地方。比如14楼样本中的第8-13行都是“利海 B”的范围,第9行好像是多了一行“退出”。
根据时间差异进行判断。如果本行与上一行时间相同,不做任何操作;否则时间不同话,查看上一行时间后面是否是字符“退出”或“企业”,若是,不做任何操作,若不是,则按要求添加一行。
这种思路不知是否符合楼主的要求,从样本上看是这样:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "tokens=1* delims=>" %%i in (a.txt) do (
  4.     if not "%%i"=="!Times!" (
  5.         for /f %%k in ("!str!") do (
  6.             if not "%%k"=="退出" (
  7.                 if not "%%k"=="企业" (
  8.                     echo,!Times!^>   退出
  9.                     echo,
  10.                 )
  11.             ) else (
  12.                 echo,
  13.             )
  14.         )
  15.     )
  16.     echo,%%i^>%%j
  17.     set "str=%%j"
  18.     set "Times=%%i"
  19. ))>b.txt
  20. pause
复制代码
代码保存为ANSI编码。未测试。

感觉上面代码还是有点不太严谨。
作者: jszw666    时间: 2023-8-21 12:06

都是高手,学习各位
作者: qixiaobin0715    时间: 2023-8-21 12:06

回复 15# 77七
应当不是这么算法,只能作为参考。比如下面代码,在我的电脑上测试,实际上用时6分多而已:
  1. @echo off
  2. (for /l %%i in (1,1,10000000) do echo,%%i)>1.txt
  3. pause
复制代码

作者: 77七    时间: 2023-8-21 12:51

本帖最后由 77七 于 2023-8-21 12:54 编辑

回复 24# qixiaobin0715


   谢谢大佬指点!
我自己也试了一下,生成 500万行的 ”19:37:30 August 16 2023>   20854企业 名称:优 美 利 A“,用for /f echo %%a用时5分钟左右。
2009-2023,14年过去了,随着计算机性能提升,效率变高了。可能是5倍。
作者: Batcher    时间: 2023-8-21 16:48

回复 25# 77七


这个差别应该跟硬件关系不太大,更主要的是多次写入和一次写入的区别,参考:
https://mp.weixin.qq.com/s/VZk0TmYUpFdCoWK9ZpgL0Q
作者: 77七    时间: 2023-8-21 20:19

回复 26# Batcher


   
谢谢站长指点!
用链接中的文本和1.bat测试,
  1. 20:12:26.72
  2. 20:12:32.40
  3. 请按任意键继续. . .
复制代码


耗时6秒左右。
作者: qixiaobin0715    时间: 2023-8-22 09:00

本帖最后由 qixiaobin0715 于 2023-8-23 11:36 编辑

由于审题不仔细,代码思路不对,此贴作废。
下面代码要比22楼要严谨些:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "tokens=1* delims=>" %%i in (a.txt) do (
  4.     if not "%%i"=="!Times!" (
  5.         if not "%%j"=="!str!" (
  6.             for /f %%k in ("%%j") do (
  7.                 if "%%k"=="企业" (
  8.                     for /f %%l in ("!str!") do (
  9.                         if not "%%l"=="退出" (
  10.                             echo,!Times!^>   退出
  11.                             echo,
  12.                         ) else (
  13.                             echo,
  14.                         )
  15.                     )
  16.                 )
  17.             )
  18.         )
  19.     )
  20.     echo,%%i^>%%j
  21.     set "str=%%j"
  22.     set "Times=%%i"
  23. )
  24. for /f %%m in ("!str!") do if not "%%m"=="退出" echo,!Times!^>   退出
  25. )>b.txt
  26. pause
复制代码

作者: qixiaobin0715    时间: 2023-8-23 11:31

这样的思路才对:
  1. @echo off
  2. set str2=退出
  3. setlocal enabledelayedexpansion
  4. (for /f "tokens=1* delims=>" %%i in (a.txt) do (
  5.     for /f %%x in ("%%j") do (
  6.         if "%%x"=="企业" (
  7.             if not "%%j"=="!str1!" (
  8.                 if not "!str2!"=="退出" (
  9.                     echo,!Times!^>   退出
  10.                     echo,
  11.                 ) else (
  12.                     if defined Times echo,
  13.                 )
  14.             )
  15.         )
  16.     )
  17.     set "Times=%%i"
  18.     echo,%%i^>%%j
  19.     for /f %%x in ("%%j") do (
  20.         if "%%x"=="企业" set "str1=%%j"
  21.         set "str2=%%x"
  22.     )
  23. )
  24. if not "!str2!"=="退出" echo,!Times!^>   退出)>b.txt
  25. pause
复制代码

作者: 娜美    时间: 2023-8-23 13:11

回复 29# qixiaobin0715


   嗯嗯, 哥哥批处理很快哦,,  条件都齐了,, 只是还欠了一种条件,  下面, 这种 上一个 "企业"  与 下一个 "企业" 之间已存在存 "退出" 字段行, 就不用再补了.   
  1. 20:39:30 August 16 2023>   企业 名称:利海 B
  2. 20:38:31 August 16 2023>   退出
  3. 20:38:31 August 16 2023>   +
  4. 20:37:30 August 16 2023>   企业 名称:海
复制代码





  18楼哥哥代码完全遵循所有条件,  所以无论文本内容如何都能正确完成
作者: qixiaobin0715    时间: 2023-8-23 16:12

换换另一个思路:
  1. @echo off
  2. set n=1
  3. setlocal enabledelayedexpansion
  4. (for /f "tokens=1* delims=>" %%i in (a.txt) do (
  5.     for /f %%x in ("%%j") do (
  6.         if "%%x"=="企业" (
  7.             if not "%%j"=="!str!" (
  8.                 if !n! equ 0 (
  9.                     echo,!Times!^>   退出
  10.                     echo,
  11.                 )
  12.             )
  13.             set n=0
  14.             set "str=%%j"
  15.         ) else if "%%x"=="退出" (
  16.             echo,%%i^>%%j
  17.             echo,
  18.             set m=0
  19.             set n=1
  20.         )
  21.     )
  22.     set "Times=%%i"
  23.     if not defined m echo,%%i^>%%j
  24.     set m=
  25. )
  26. if !n! equ 0 echo,!Times!^>   退出)>b.txt
  27. pause
复制代码

作者: 娜美    时间: 2023-8-23 17:08

回复 31# qixiaobin0715


对对对, 和18楼哥哥一样,  完全正确了, 哥哥你这思路就很好嘛,    给代码赋予了智慧, 就像Ai一样灵活地工作,,批处理还能很快不到5分钟
作者: 娜美    时间: 2023-8-23 21:53

本帖最后由 娜美 于 2023-8-23 23:32 编辑

回复 31# qixiaobin0715


     检测发现会改变原本某些行内容, 特别是有 "!" 号行   问题是似乎不支持在 ">" 之后某些字符, 但无论如何, 与之没有关系的这些行不应该会受到影响或强制改变他原样

用符号测验原来会吃掉一大半字符
20:39:30 August 16 2023> ! ++
20:39:30 August 16 2023>   ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ " 用符号测验出原因了, 原来是会吃掉在 ">" 之后的一大半字符,
作者: qixiaobin0715    时间: 2023-8-24 08:28

回复 33# 娜美
出现这种情况的原因见 http://www.bathome.net/thread-11193-1-1.html
但是我觉得在这里for循环体内使用setlocal和endlocal不适合,因为要兼顾到当前行上面的若干行,endlocal后,前面所有设置的变量都消失了。还是考虑其它程序或方法。
作者: qixiaobin0715    时间: 2023-8-24 08:42

其它变量还可以想办法解决,31楼代码第22行变量Times的设置不好处理,因为你要增加的“退出”那一行,要使用上一行的时间。
作者: qixiaobin0715    时间: 2023-8-24 11:30

本帖最后由 qixiaobin0715 于 2023-8-24 13:21 编辑

想了想,楼上说的有点太绝对,好像可以在特定位置添加setlocal和endlocal组合来实现部分特殊字符显示原样输出的问题,代码未测试:
  1. @echo off
  2. (for /f "tokens=1* delims=>" %%i in (a.txt) do (
  3.     for /f %%x in ("%%j") do (
  4.         if "%%x"=="企业" (
  5.             setlocal enabledelayedexpansion
  6.             if not "%%j"=="!str!" (
  7.                 if "!n!"=="0" (
  8.                     echo,!Times!^>   退出
  9.                     echo,
  10.                 ) else if defined n (
  11.                     echo,
  12.                 )
  13.             )
  14.             endlocal
  15.             set n=0
  16.             set "str=%%j"
  17.         ) else if "%%x"=="退出" (
  18.             set n=1
  19.         )
  20.     )
  21.     echo,%%i^>%%j
  22.     set "Times=%%i"
  23. ))>b.txt
  24. if %n% equ 0 echo,%Times%^>   退出>>b.txt
  25. pause
复制代码
请自行测试。
作者: 娜美    时间: 2023-8-24 15:36

回复 36# qixiaobin0715


  确实可以解决原样输出的问题哦 但如果 名称 部分特殊字符发现一律会当不相同处理, 会插入一行,   特别是含有 "!" 字符,    似乎是识别字符不够多

为了测验,  我偿试举了一些含有 "!" 字符 例试试
20:37:30 August 16 2023> 企业 名称:美!
20:37:30 August 16 2023> 企业 名称:美!


20:37:30 August 16 2023> 企业 名称:美
20:37:30 August 16 2023> 企业 名称:美


多特殊字符, 批处理不知道能够支持多少
  1. 20:37:30 August 16 2023>   企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  2. 20:39:30 August 16 2023> ! ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  3. 20:37:30 August 16 2023>   企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  4. 20:39:30 August 16 2023> ! ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  5. 20:37:30 August 16 2023>   企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  6. 20:39:30 August 16 2023> * ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  7. 20:39:30 August 16 2023> ? ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  8. 20:37:30 August 16 2023>   企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
  9. 20:39:30 August 16 2023>   +
  10. 20:39:30 August 16 2023>   企业 名称:利海 B
复制代码


作者: qixiaobin0715    时间: 2023-8-24 15:44

那是没有考虑含有“企业”的行的情况,请不要纠结这个问题了。还是以实际存在的问题为主,否则每次写代码都要面面俱到,就会出现代码复杂,效率低下的问题。
作者: 娜美    时间: 2023-8-24 15:47

回复 38# qixiaobin0715 嗯嗯 好吧
作者: qixiaobin0715    时间: 2023-8-25 11:49

看到在12楼你有显示新增行的需求,最简单的办法是在新增行中做一个标记,比如在“退出”前面加个不常用的符号,如“`退出”,使用findstr /n命令查找这些新增行。缺点是输出结果中,新增行多出了一个符号。
以36楼的代码为例:
1.将代码第8、24行中的“退出”改为“`退出”。
2.在pause前一行增加一行代码:
  1. (for /f "delims=:" %%i in ('findstr /r /n "`退出" b.txt') do echo,%%i)>AddedLines.txt
复制代码

作者: 娜美    时间: 2023-8-25 16:19

回复 40# qixiaobin0715


   哦哦,  代码会改变一些与之没有关系的行在每1行后面都会加上 ">"    虽然没有多大问题,  但不应该影响或者改变与之没有那些关系的行,  

  1. 20:39:30 August 16 2023>   企业 名称:利海 B
  2. Intel graphics 5.2.0.10094
  3. 检测到的设备:  8 CPUs, 1 NVidia GPU, 1 Intel Graphics
  4. 系统目录 - C:\Windows\SYSNATIVE
复制代码

作者: qixiaobin0715    时间: 2023-8-25 16:37

本帖最后由 qixiaobin0715 于 2023-8-26 09:31 编辑

回复 41# 娜美
前面让你提供真实文本,样本不典型。修改了输出样式,这样看起来更一致:
  1. @echo off
  2. (for /f "tokens=1* delims=>" %%i in (a.txt) do (
  3.     set m=
  4.     for /f %%x in ("%%j") do (
  5.         if "%%x"=="企业" (
  6.             set "str1=%%j"
  7.             setlocal enabledelayedexpansion
  8.             if not "!str1!"=="!str2!" (
  9.                 if defined n (
  10.                     echo,!Times!^>   `退出
  11.                     echo,
  12.                 )
  13.             )
  14.             endlocal
  15.             set n=0
  16.             set "str2=%%j"
  17.         ) else if "%%x"=="退出" (
  18.             set m=1
  19.             set n=
  20.         )
  21.     )
  22.     if not "%%j"=="" (echo,%%i^>%%j) else echo,%%i
  23.     if defined m echo,
  24.     set "Times=%%i"
  25. ))>b.txt
  26. if %n% equ 0 echo,%Times%^>   `退出>>b.txt
  27. (for /f "delims=:" %%i in ('findstr /r /n "`退出" b.txt') do echo,%%i)>AddedLines.txt
  28. pause
复制代码
再试试看看。
作者: 娜美    时间: 2023-8-25 20:16

回复 42# qixiaobin0715


   OK 了
作者: qixiaobin0715    时间: 2023-8-26 09:17

本帖最后由 qixiaobin0715 于 2023-8-26 09:48 编辑

回复 37# 娜美
实际上好好看看34楼链接的帖子,就能解决37楼的问题。
总的原则是在setlocal和endlocal之外设置变量,在其内部使用设置的变量。
33楼和37楼其实是同一类的问题,只不过前者是显示,后者是比较,所以解决的方法也类似。
我已把42楼的代码修改,看看是否能解决你的问题。
作者: 娜美    时间: 2023-8-26 10:37

回复 44# qixiaobin0715


   Yeah,   很灵巧的解决某些原字符问题 , 和18楼哥哥的都能正确完成

此题终结,  谢谢以上参与题目的所有朋友




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2