标题: [文本处理] 批处理怎样按条件插入行填补行? [打印本页]
作者: 娜美 时间: 2023-8-19 22:16 标题: 批处理怎样按条件插入行填补行?
本帖最后由 娜美 于 2023-8-20 14:04 编辑
补充一些a文本- a.txt ANSI编码
-
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:35 August 16 2023> +
- 19:37:36 August 16 2023> 企业 名称:海
- 19:37:39 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> 退出
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
-
-
-
- 企业"字段 至 "企业"字段 之间 或许会有很多行, 示例中只是尽量缩短没影响的行
-
- if 如果遇到有"企业"字段 与 "企业"字段 之间的名称不相同, 且它们中间没有 "退出"字段, 则需要添加插入 "退出"字段行, 如果他们字段之间有了 "退出"字段, 则跳过忽略, 日期时间填补请使用有"企业"字段的上一行日期时间
- if 如果有"企业"字段的行 一直至有 "退出"字段行中, 它们名称仍然都是相同的, , 则不做任何动作
-
- 名称有可能会使用某些字符号, 希望可尽量支持多些名称字符
- PowerShell awk bat
-
- 或许 可以将 ">" 看成分隔符处理吧
-
- >b.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> 退出
-
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> 退出
-
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> 退出
-
- 19:37:36 August 16 2023> 企业 名称:海
- 19:37:39 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> 退出
-
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
复制代码
作者: 77七 时间: 2023-8-19 23:08
a.txt- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:36 August 16 2023> 企业 名称:利海 B
- 19:37:39 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
复制代码
执行
- @echo off
- setlocal enabledelayedexpansion
- (for /f "useback tokens=1* delims=:" %%f in (`findstr /n .* "a.txt"`) do (
- for /f "tokens=1* delims=>" %%a in ("%%g") do (
- if defined name (
- if "!name!" neq "%%b" (
- if "%%b" neq " 退出 " (
- echo !t!^> 退出
- set name=%%b
- ) else set name=
- )
- ) else set name=%%b
- set t=%%a
- )
- echo=%%g
- ))>b.txt
- endlocal
- pause
复制代码
b.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:30 August 16 2023> 退出
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:32 August 16 2023> 退出
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:34 August 16 2023> 退出
- 19:37:36 August 16 2023> 企业 名称:利海 B
- 19:37:39 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
复制代码
作者: 娜美 时间: 2023-8-19 23:29
本帖最后由 娜美 于 2023-8-19 23:42 编辑
回复 2# 77七
字段与字段之间行数不固定哦, 字段与字段之间 没有"退出" 补一行就行, 似乎补多了- 如果中间行数多几行情况
- a.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
-
- 如果"企业" 与 "企业"字段之间没有"退出" 字段, 在有"企业"字段上一行添加一行就行, 似乎在企业下面也添加了, 重复添加了
-
- >b.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:30 August 16 2023> 退出
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> 退出
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:32 August 16 2023> 退出
- 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七
好的
例如这样的样例- a.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:36 August 16 2023> 企业 名称:利海 B
- 20:37:30 August 16 2023> +
- 20:37:30 August 16 2023> +
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
-
- >b.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> 退出
-
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> 退出
-
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> 退出
-
- 19:37:36 August 16 2023> 企业 名称:利海 B
- 20:37:30 August 16 2023> +
- 20:37:30 August 16 2023> +
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
复制代码
作者: 77七 时间: 2023-8-20 00:01
本帖最后由 77七 于 2023-8-20 00:08 编辑
回复 5# 娜美
- @echo off
- setlocal enabledelayedexpansion
- (for /f "useback tokens=1* delims=:" %%f in (`findstr /n .* "a.txt"`) do (
- set str=%%g
- set str1=!str:企业=!
- if "!str1:退出=!" neq "!str!" (
- for /f "tokens=1* delims=>" %%a in ("%%g") do (
- if defined name (
- if "!name!" neq "%%b" (
- if "%%b" neq " 退出 " (
- echo !t!^> 退出
- set name=%%b
- ) else set name=
- )
- ) else set name=%%b
- set t=%%a
- )
- )
- echo=%%g
- ))>b.txt
- endlocal
- pause
复制代码
作者: 娜美 时间: 2023-8-20 00:17
本帖最后由 娜美 于 2023-8-20 00:24 编辑
回复 6# 77七
这次基本对了, 不过补的时间不是上一行时间, 只是时间补错了 会寻致下一步不能正确计算时间 请帮忙再看下
作者: 77七 时间: 2023-8-20 00:23
回复 7# 娜美
- @echo off
- setlocal enabledelayedexpansion
- (for /f "useback tokens=1* delims=:" %%f in (`findstr /n .* "a.txt"`) do (
- set str=%%g
- set str1=!str:企业=!
- if "!str1:退出=!" neq "!str!" (
- for /f "tokens=1* delims=>" %%a in ("%%g") do (
- if defined name (
- if "!name!" neq "%%b" (
- if "%%b" neq " 退出 " (
- echo !t!^> 退出
- set name=%%b
- ) else set name=
- )
- ) else set name=%%b
- )
- )
- for /f "tokens=1* delims=>" %%a in ("%%g") do (
- set t=%%a
- )
- echo=%%g
- ))>b.txt
- endlocal
- pause
复制代码
修改时忘记考虑了。
作者: 娜美 时间: 2023-8-20 00:28
回复 8# 77七
多谢哥哥基本正确了, 晚安 我明天再细试一下
哥哥晚安
作者: Nsqs 时间: 2023-8-20 05:33
本帖最后由 Nsqs 于 2023-8-20 07:48 编辑
ps没那么复杂- $data=gc a.txt
- $s=New-Object 'System.Collections.Generic.List[string][]' 3
- $f='企业'
- for($i=0;$i -lt $data.Count;$i++){
- if($data[$i] -match $f){
- [int]$c=$c%2+1
- $s[$c]=[regex]::Matches($data[$i],"$f.+")
- if($s[1] -ne $s[2]){
- $b=$data[$i-1]
- $data[$i-1]="$($b)`r`n$([regex]::Matches($b,'.+>')) 退出"
- }
- }
- }
- $data=$data -split '\r\n'
- $data[0..($data.Count-2)]>b.txt
复制代码
bat- @echo off&setlocal enabledelayedexpansion
- set n=100
- for /f "delims=" %%1 in (a.txt)do set /a n+=1&call set "#%%n%%=%%1"
- for /f "tokens=1,2,6* delims=#= " %%1 in ('set #')do (
- set /a a=%%1
- set "line=%%3%%4%%5"
- set d=!line:* =!
- set d=!d:~,2!
- if !d!==企业 (
- call set "s!c!=!line!"
- set /a c=c %% 2+1
- if !s1! neq !s2! (
- set /a b=a-1
- call set "#!b!#=%%#!b!:+=%%退出"
- )))
- (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 较为理想, 但是在实际文本中会在第一行产生多余的一行 " 退出 " 其他的还产生重复插入字段情况
例如, 以下这种情况在样式例子中不会, 但在实际文本中会发生如下情况, 多了一行- a.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> 退出
- 19:37:32 August 16 2023> 企业 名称:海
-
-
- 像这种已存在条件情况, 也会重复插入了
- >b.txt
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> 退出
- 19:37:31 August 16 2023> 退出
- 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个条件判断呗, 耍检查有"企业"字段 与 "企业"字段 之间的名称是否相同, 其中是否存在有 "退出"字段的行
- if 如果遇到有"企业"字段 与 "企业"字段 之间的名称不相同, 且它们中间没有 "退出"字段, 则需要添加插入 "退出"字段行, 日期时间填补请使用有"企业"字段的上一行日期时间
- if 如果有"企业"字段的行 一直至有 "退出"字段行中, 它们名称仍然都是相同的, , 则不做任何动作
- a.txt ANSI编码
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:35 August 16 2023> +
- 19:37:36 August 16 2023> 企业 名称:利海 B
- 19:37:39 August 16 2023> 退出
-
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:32 August 16 2023> 企业 名称:利海 B
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:33 August 16 2023> +
- 19:37:34 August 16 2023> 企业 名称:利海 01:C (A)
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:35 August 16 2023> +
- 19:37:36 August 16 2023> 企业 名称:利海 B
- 20:37:30 August 16 2023> +
- 20:37:30 August 16 2023> +
- 20:37:30 August 16 2023> 企业 名称:利海 B
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> +
- 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
-
- 19:37:30 August 16 2023> 企业 名称:优 美 利 A
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> ++++
- 19:37:31 August 16 2023> 退出
- 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代码- $inf="a.txt"
- $otf="b.txt"
- $r='企业\s*名称.+|退出'
-
- $inf=[io.file]::ReadAllLines($pwd.path+"\$inf",[text.encoding]::Default)
- if(!$inf){exit}
- $n=0
- $f=[System.IO.StringWriter]::new()
-
- for($i=0;$i -lt $inf.Length;$i++){
- if(!$inf[$i]){$f.WriteLine();continue}
-
- if($n -and $n[1]){
-
- $m=[regex]::Match($inf[$i],"$r")
- if($m.success -and ($m.value -eq "退出")){$f.WriteLine($inf[$i]);$n=0;continue}
- #if($m.success -and ($m.value.split(':')[1] -eq $n.split(':')[1])){$f.WriteLine($inf[$i]);$n=0;continue}
- if($m.success -and ($m.value -eq $n[1])){$f.WriteLine($inf[$i]);$n[0]=$i;continue}
-
- if($m.success){
- $z=[regex]::Match($inf[$n[0]],">\s*")
- echo "从原文本第 $i 行后插入"
- $f.WriteLine($inf[$n[0]].substring(0,$z.index+$z.length)+"退出");
- $f.WriteLine($inf[$i])
- $n=@($i,$m.value);continue}
-
- $f.WriteLine($inf[$i]);$n[0]=$i;continue
- }
-
- $m=[regex]::Match($inf[$i],"$r")
- if($m.success -and ($m.value -ne "退出")){$n=@($i,$m.value)}
- $f.WriteLine($inf[$i])
- }
-
- if($n){
- $z=[regex]::Match($inf[$n[0]],">\s*")
- echo "从原文本末尾插入"
- $f.WriteLine($inf[$n[0]].substring(0,$z.index+$z.length)+"退出");
- }
-
- [io.file]::WriteAllText($pwd.path+"\$otf",$f.ToString(),[text.encoding]::default)
- pause;$f.Dispose()
复制代码
作者: 娜美 时间: 2023-8-20 15:47
回复 18# Five66
完全正确, 谢谢哥哥
作者: Nsqs 时间: 2023-8-20 18:09
本帖最后由 Nsqs 于 2023-8-20 18:59 编辑
- $data=gc a.txt
- $s=New-Object 'System.Collections.Generic.List[string][]' 3
- $f='企业'
- [string[]]$x=@{}
- @(for($i=0;$i -lt $data.Count;$i++){
- $x+=$data[$i]
- if($data[$i] -match $f){
- [int]$c=$c%2+1
- $s[$c]=[regex]::Matches($data[$i],"$f.+")
- if($s[1] -ne $s[2] -and $x -notmatch '退出'){
- $b=$data[$i-1]
- if($i -gt 1){[PSCustomObject]@{'Changed'="Source:`t$("$i".PadLeft(4))";Source=$($data[$i-1])}}
- $r="$([regex]::Matches($b,'.+>')) 退出"
- $data[$i-1]="$($b)`r`n$r"
- if($i -gt 1){[PSCustomObject]@{'Changed'="New`t$("$($i+1)".PadLeft(4))";Source=$r}}
- }
- $x=@{}
- }
- })|ft -Wrap -AutoSize
- $data=$data -split '\r\n'
- $data[0..($data.Count-2)]>b.txt
- cmd /c pause
复制代码
不知道是不是这样呢?
作者: hfxiang 时间: 2023-8-20 20:39
回复 1# 娜美
用awk可以实现:- 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行好像是多了一行“退出”。
根据时间差异进行判断。如果本行与上一行时间相同,不做任何操作;否则时间不同话,查看上一行时间后面是否是字符“退出”或“企业”,若是,不做任何操作,若不是,则按要求添加一行。
这种思路不知是否符合楼主的要求,从样本上看是这样:- @echo off
- setlocal enabledelayedexpansion
- (for /f "tokens=1* delims=>" %%i in (a.txt) do (
- if not "%%i"=="!Times!" (
- for /f %%k in ("!str!") do (
- if not "%%k"=="退出" (
- if not "%%k"=="企业" (
- echo,!Times!^> 退出
- echo,
- )
- ) else (
- echo,
- )
- )
- )
- echo,%%i^>%%j
- set "str=%%j"
- set "Times=%%i"
- ))>b.txt
- pause
复制代码
代码保存为ANSI编码。未测试。
感觉上面代码还是有点不太严谨。
作者: jszw666 时间: 2023-8-21 12:06
都是高手,学习各位
作者: qixiaobin0715 时间: 2023-8-21 12:06
回复 15# 77七
应当不是这么算法,只能作为参考。比如下面代码,在我的电脑上测试,实际上用时6分多而已:- @echo off
- (for /l %%i in (1,1,10000000) do echo,%%i)>1.txt
- 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测试,
- 20:12:26.72
- 20:12:32.40
- 请按任意键继续. . .
复制代码
耗时6秒左右。
作者: qixiaobin0715 时间: 2023-8-22 09:00
本帖最后由 qixiaobin0715 于 2023-8-23 11:36 编辑
由于审题不仔细,代码思路不对,此贴作废。
下面代码要比22楼要严谨些:- @echo off
- setlocal enabledelayedexpansion
- (for /f "tokens=1* delims=>" %%i in (a.txt) do (
- if not "%%i"=="!Times!" (
- if not "%%j"=="!str!" (
- for /f %%k in ("%%j") do (
- if "%%k"=="企业" (
- for /f %%l in ("!str!") do (
- if not "%%l"=="退出" (
- echo,!Times!^> 退出
- echo,
- ) else (
- echo,
- )
- )
- )
- )
- )
- )
- echo,%%i^>%%j
- set "str=%%j"
- set "Times=%%i"
- )
- for /f %%m in ("!str!") do if not "%%m"=="退出" echo,!Times!^> 退出
- )>b.txt
- pause
复制代码
作者: qixiaobin0715 时间: 2023-8-23 11:31
这样的思路才对:- @echo off
- set str2=退出
- setlocal enabledelayedexpansion
- (for /f "tokens=1* delims=>" %%i in (a.txt) do (
- for /f %%x in ("%%j") do (
- if "%%x"=="企业" (
- if not "%%j"=="!str1!" (
- if not "!str2!"=="退出" (
- echo,!Times!^> 退出
- echo,
- ) else (
- if defined Times echo,
- )
- )
- )
- )
- set "Times=%%i"
- echo,%%i^>%%j
- for /f %%x in ("%%j") do (
- if "%%x"=="企业" set "str1=%%j"
- set "str2=%%x"
- )
- )
- if not "!str2!"=="退出" echo,!Times!^> 退出)>b.txt
- pause
复制代码
作者: 娜美 时间: 2023-8-23 13:11
回复 29# qixiaobin0715
嗯嗯, 哥哥批处理很快哦,, 条件都齐了,, 只是还欠了一种条件, 下面, 这种 上一个 "企业" 与 下一个 "企业" 之间已存在存 "退出" 字段行, 就不用再补了. - 20:39:30 August 16 2023> 企业 名称:利海 B
- 20:38:31 August 16 2023> 退出
- 20:38:31 August 16 2023> +
- 20:37:30 August 16 2023> 企业 名称:海
复制代码
18楼哥哥代码完全遵循所有条件, 所以无论文本内容如何都能正确完成
作者: qixiaobin0715 时间: 2023-8-23 16:12
换换另一个思路:- @echo off
- set n=1
- setlocal enabledelayedexpansion
- (for /f "tokens=1* delims=>" %%i in (a.txt) do (
- for /f %%x in ("%%j") do (
- if "%%x"=="企业" (
- if not "%%j"=="!str!" (
- if !n! equ 0 (
- echo,!Times!^> 退出
- echo,
- )
- )
- set n=0
- set "str=%%j"
- ) else if "%%x"=="退出" (
- echo,%%i^>%%j
- echo,
- set m=0
- set n=1
- )
- )
- set "Times=%%i"
- if not defined m echo,%%i^>%%j
- set m=
- )
- if !n! equ 0 echo,!Times!^> 退出)>b.txt
- 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组合来实现部分特殊字符显示原样输出的问题,代码未测试:- @echo off
- (for /f "tokens=1* delims=>" %%i in (a.txt) do (
- for /f %%x in ("%%j") do (
- if "%%x"=="企业" (
- setlocal enabledelayedexpansion
- if not "%%j"=="!str!" (
- if "!n!"=="0" (
- echo,!Times!^> 退出
- echo,
- ) else if defined n (
- echo,
- )
- )
- endlocal
- set n=0
- set "str=%%j"
- ) else if "%%x"=="退出" (
- set n=1
- )
- )
- echo,%%i^>%%j
- set "Times=%%i"
- ))>b.txt
- if %n% equ 0 echo,%Times%^> 退出>>b.txt
- 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> 企业 名称:美
多特殊字符, 批处理不知道能够支持多少
- 20:37:30 August 16 2023> 企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:39:30 August 16 2023> ! ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:37:30 August 16 2023> 企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:39:30 August 16 2023> ! ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:37:30 August 16 2023> 企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:39:30 August 16 2023> * ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:39:30 August 16 2023> ? ` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:37:30 August 16 2023> 企业 名称:美` ~!@#$%^&*()_+=-{}|[]\:;'<>?,./ "0123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP
- 20:39:30 August 16 2023> +
- 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前一行增加一行代码:- (for /f "delims=:" %%i in ('findstr /r /n "`退出" b.txt') do echo,%%i)>AddedLines.txt
复制代码
作者: 娜美 时间: 2023-8-25 16:19
回复 40# qixiaobin0715
哦哦, 代码会改变一些与之没有关系的行在每1行后面都会加上 ">" 虽然没有多大问题, 但不应该影响或者改变与之没有那些关系的行,
- 20:39:30 August 16 2023> 企业 名称:利海 B
- Intel graphics 5.2.0.10094
- 检测到的设备: 8 CPUs, 1 NVidia GPU, 1 Intel Graphics
- 系统目录 - C:\Windows\SYSNATIVE
复制代码
作者: qixiaobin0715 时间: 2023-8-25 16:37
本帖最后由 qixiaobin0715 于 2023-8-26 09:31 编辑
回复 41# 娜美
前面让你提供真实文本,样本不典型。修改了输出样式,这样看起来更一致:- @echo off
- (for /f "tokens=1* delims=>" %%i in (a.txt) do (
- set m=
- for /f %%x in ("%%j") do (
- if "%%x"=="企业" (
- set "str1=%%j"
- setlocal enabledelayedexpansion
- if not "!str1!"=="!str2!" (
- if defined n (
- echo,!Times!^> `退出
- echo,
- )
- )
- endlocal
- set n=0
- set "str2=%%j"
- ) else if "%%x"=="退出" (
- set m=1
- set n=
- )
- )
- if not "%%j"=="" (echo,%%i^>%%j) else echo,%%i
- if defined m echo,
- set "Times=%%i"
- ))>b.txt
- if %n% equ 0 echo,%Times%^> `退出>>b.txt
- (for /f "delims=:" %%i in ('findstr /r /n "`退出" b.txt') do echo,%%i)>AddedLines.txt
- 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 |