Board logo

标题: [文本处理] 求助,用批处理如何删除文件里的某些行。 [打印本页]

作者: smatenchen    时间: 2022-11-9 21:20     标题: 求助,用批处理如何删除文件里的某些行。

本帖最后由 smatenchen 于 2022-11-11 22:18 编辑


求助,用批处理如何删除文件里的某些行。


1,
问题,有一个文件 1.txt,其内容如下,

……
[111]
……
[222]
……
……
……
……
[333]
……


其中……代表已省略的内容。


2,
要求,
删除 1.txt 里[222]所在行之下,[333]所在行之上的各行,其余要保留。
即,只删除[222]与[333]之间的各行,其余要保留。


3,
请大神们帮忙!感谢!

作者: smatenchen    时间: 2022-11-9 21:23

本帖最后由 smatenchen 于 2022-11-10 14:54 编辑

回复 1# Batcher

1,
请大神帮忙!感谢!
作者: smatenchen    时间: 2022-11-9 21:24

本帖最后由 smatenchen 于 2022-11-10 14:55 编辑

回复 1# qixiaobin0715

1,
请大神帮忙!感谢!
作者: Batcher    时间: 2022-11-10 09:20

回复 2# smatenchen


回复 2# Batcher

即使手工写一个,也没用,论坛程序不会通知的。
作者: smatenchen    时间: 2022-11-10 14:07

回复 4# Batcher


作者: hfxiang    时间: 2022-11-10 14:28

回复 1# smatenchen


   
下载gawk( http://bcn.bathome.net/tool/4.1.0/gawk.exe ),将:
  1. ……
  2. [111]
  3. ……
  4. [222]
  5. ……
  6. ……
  7. ……
  8. ……
  9. [333]
  10. ……
复制代码
以ANSI格式保存为1.txt
执行:
  1. gawk "/\[222\]/{while((getline)>0)if(/\[333\]/){print;next}}1"  1.txt>2.txt
复制代码
结果(2.txt):
  1. ……
  2. [111]
  3. ……
  4. [333]
  5. ……
复制代码

作者: smatenchen    时间: 2022-11-10 14:37

回复 6# hfxiang


1,
非常感谢!


2,
感谢大神出手帮忙!


3,
你的方法,需要借助其它应用程序。


有办法,只用批处理就能解题吗?


请试试,只用批处理去解题的方法。
作者: hfxiang    时间: 2022-11-10 14:50

回复 7# smatenchen
  1. @echo off
  2. @rem 保存为ANSI格式
  3. setlocal enabledelayedexpansion
  4. set /a b=1
  5. for /f %%a in (1.txt) do (
  6. if "%%~a"=="[222]" set /a b=0
  7. if "%%~a"=="[333]" set /a b=1
  8. if !b! EQU 1 echo;%%a
  9. )
复制代码

作者: smatenchen    时间: 2022-11-10 14:50

回复 1# Batcher


1,
非常感谢!


2,
感谢你的提醒!
看来还需要提高才行。


3,
我认真修改了一下,这次行了吗?
请大神反馈一下!感谢!
作者: qixiaobin0715    时间: 2022-11-10 15:41

回复 8# hfxiang
代码第7、8行互换一下更确切。
作者: hfxiang    时间: 2022-11-10 15:44

回复 10# qixiaobin0715


    这个不能互换,不信你测试一下即知
作者: qixiaobin0715    时间: 2022-11-10 15:52

本帖最后由 qixiaobin0715 于 2022-11-10 16:01 编辑

回复 11# hfxiang
楼主表达不清,我认为是[222]、[333]这2行要么都要删除,要么都保留。
都删除:
  1. if "%%~a"=="[222]" set /a b=0
  2. if !b! EQU 1 echo;%%a
  3. if "%%~a"=="[333]" set /a b=1
复制代码
都保留:
  1. if "%%~a"=="[333]" set /a b=1
  2. if !b! EQU 1 echo;%%a
  3. if "%%~a"=="[222]" set /a b=0
复制代码

作者: smatenchen    时间: 2022-11-10 16:37

本帖最后由 smatenchen 于 2022-11-13 10:10 编辑

回复 8# hfxiang qixiaobin0715 Batcher idwma BAT221110


1,
非常感谢!


2,
要求,
删除 1.txt 里[222]所在行之下,[333]所在行之上的各行,其余要保留。


要删除[222]之下,[333]之上的中间各行。
即,只删除[222]与[333]之间的各行,其余要保留。


再说白一点,我是想删除 1.txt 里的某一段,但文件结构不能改变,
而[222],[333]是文件结构的一部分,故不能删除。


3,
  1. if "%%~a"=="[222]" set /a b=0
  2. if "%%~a"=="[333]" set /a b=1
  3. if !b! EQU 1 echo;%%a
复制代码

这个解法挺巧妙,没想到可以如此轻巧。


比较头疼,批处理命令似乎并不能删除文件里的内容,看似最后也只能用>,
>>去生成所要的新文件,而后再去替换。


4,
你的代码不错,给了我很大的提示。感谢!


我之前想了好久,感觉其解法代码会很复杂,且最后,也就只能用>,
>>去生成所要的新文件,而不能直接删除原文件 1.txt 里的内容。


现在看来,我把问题想得过于复杂了,没找到巧妙的解法。


5,
感谢大神们的帮忙,似乎问题差不多有解法了。
非常感谢!
作者: smatenchen    时间: 2022-11-10 16:48

本帖最后由 smatenchen 于 2022-11-11 21:45 编辑

回复 12# qixiaobin0715 hfxiang Batcher


1,
非常感谢!


2,
各位大神的解法,都不错,我觉得。


3,
非常感谢!
作者: qixiaobin0715    时间: 2022-11-10 16:50

回复 8# hfxiang
你必须把代码交代的清清楚楚明明白白的,他才会明白。
作者: smatenchen    时间: 2022-11-10 17:00

回复 15# qixiaobin0715 hfxiang Batcher


1,
非常感谢!


2,
恳请大神写出完整解法代码,我去运行一下,就知有无效果了。


3,
麻烦大神了!非常感谢!
作者: idwma    时间: 2022-11-10 18:06

当bat用
  1. powershell "(gc 1.txt)-join \"`r`n\" -replace '(?s)(?<=\[222\]..).+(?=\[333\])'|sc 1.txt"
复制代码

作者: smatenchen    时间: 2022-11-10 23:45

回复 17# idwma qixiaobin0715 hfxiang


1,
非常感谢!


2,
只用cmd命令,也可以办到吗?
若可以,请帮忙写出解法代码。


3,
非常感谢!
作者: BAT221110    时间: 2022-11-11 09:52

楼上兄弟的方法没问题啊


回复  qixiaobin0715 hfxiang Batcher


1,
非常感谢!


2,
各位大神的解法,看似都不能解题, ...
smatenchen 发表于 2022-11-10 16:48

作者: qixiaobin0715    时间: 2022-11-11 11:28

参考8楼兄弟的代码:
  1. @echo off
  2. (for /f "delims=" %%i in (1.txt) do (
  3.     if "%%i"=="[333]" set n=
  4.     if not defined n echo,%%i
  5.     if "%%i"=="[222]" set n=true
  6. ))>temp.log
  7. move temp.log 1.txt
复制代码

作者: hfxiang    时间: 2022-11-11 13:57

回复 20# qixiaobin0715


相对于纯P,俺更喜欢第3方工具,如gawk、sed:

1.删除两匹配行([222],[333])之间的行,两匹配行都保留
  1. gawk "/\[222\]/{print;while((getline)>0)if(/\[333\]/){print;next}}1" 1.txt>2.txt
复制代码
  1. sed -i -r -e "/\[222\]/,/\[333\]/{/\[222\]/p;/\[333\]/p;d;}" 1.txt
复制代码
2.保留首匹配行
  1. gawk "/\[222\]/{print;while((getline)>0)if(/\[333\]/)next}1" 1.txt>2.txt
复制代码
  1. sed -i -r -e "/\[222\]/,/\[333\]/{/\[222\]/p;d;}" 1.txt
复制代码
3.保留末匹配行
  1. gawk "/\[222\]/{while((getline)>0)if(/\[333\]/){print;next}}1" 1.txt>2.txt
复制代码
  1. sed -i -r -e "/\[222\]/,/\[333\]/{/\[333\]/p;d;}" 1.txt
复制代码
4.两匹配行都不保留
  1. gawk "/\[222\]/,/\[333\]/{next}1" 1.txt>2.txt
复制代码
  1. sed -i -r -e "/\[222\]/,/\[333\]/d" 1.txt
复制代码

作者: qixiaobin0715    时间: 2022-11-11 14:22

回复 21# hfxiang
代码简洁,效率高。不过有些人看着这么多斜杠反斜杠会头晕,实际上我也是
作者: smatenchen    时间: 2022-11-11 22:22

本帖最后由 smatenchen 于 2022-11-13 10:11 编辑

回复 8# hfxiang idwma qixiaobin0715 BAT221110 Batcher

  1. @echo off
  2. @rem 保存为ANSI格式
  3. setlocal enabledelayedexpansion
  4. set /a b=1
  5. for /f %%a in (1.txt) do (
  6. if "%%~a"=="[222]" set /a b=0
  7. if "%%~a"=="[333]" set /a b=1
  8. if !b! EQU 1 echo;%%a
  9. )
复制代码



1,
非常感谢!


2,
你的解法不错,给了我很大的提示。感谢!


3,
我遇到了难题,故在第1楼发帖时特意简化了问题,既然大神们如此轻巧就给了我帮忙,
看来最终的难题,没有那么难办。


现将完整问题写出来,请大神们帮忙解决我最终的难题。


4,
问题,
有一个文件 1.txt,其内容如下,


……
[???]
……
[222]
……
……
……
……
[???]
……


其中……代表已省略的内容。


文件由类似[222]这样的多个段落组成,[???]代表段落名称未知。
[222],[???],这些代表文件结构。


凡是出现[???]时,就代表已是另一个段落了。


[222],这个段落名称是已知的,其它段落名称未知。


[222],这个段落出现在文件里第几行,是随机的,
一旦出现后,其位置就固定了。


5,
要求,
删除 1.txt 里[222],这个段落里的各行,其它段落不能删除,
[222]这个段落名称行要保留,文件结构不能破坏。


6,
请大神们帮忙,写出解法代码!
非常感谢!
作者: smatenchen    时间: 2022-11-11 22:43

本帖最后由 smatenchen 于 2022-11-13 10:12 编辑

回复 8# hfxiang idwma qixiaobin0715 BAT221110 Batcher
  1. @echo off
  2. @rem 保存为ANSI格式
  3. setlocal enabledelayedexpansion
  4. set /a b=1
  5. for /f %%a in (1.txt) do (
  6. if "%%~a"=="[222]" set /a b=0
  7. if "%%~a"=="[333]" set /a b=1
  8. if !b! EQU 1 echo;%%a
  9. )
复制代码


1,
非常感谢!


2,
if "%%~a"=="[222]" set /a b=0
if "%%~a"=="[333]" set /a b=1
if !b! EQU 1 echo;%%a


有这些代码,会把[222]这一行也删除,这就破坏文件结构了。


我说的,没错吧?这应是个bug了,一点小瑕疵。


3,
请答疑!
非常感谢!
作者: smatenchen    时间: 2022-11-11 22:52

回复 19# BAT221110 qixiaobin0715 hfxiang idwma


1,
非常感谢!


2,
是的,大神们的解法都很不错,给了我很大的提示。


我刚开始时,没看明白。


不过,有的代码有点小bug。
作者: BAT221110    时间: 2022-11-12 06:25

对的。似乎BAT没有直接编辑文件的内置命令。如果能用外置命令的话,用ED、AWK这些行编辑器都能搞定。


回复  hfxiang qixiaobin0715 Batcher idwma BAT221110


1,
非常感谢!


2,
要求,
删除 1.t ...
smatenchen 发表于 2022-11-10 16:37

作者: smatenchen    时间: 2022-11-12 09:34

回复 26# BAT221110


作者: terse    时间: 2022-11-12 11:45

本帖最后由 terse 于 2022-11-12 11:47 编辑

纯p
  1. @echo off
  2. rem 存为ANSI文件
  3. for /f "delims=:" %%a in ('findstr /bln "[222] [333]" 1.txt') do (
  4.       if defined a (set b=%%a) else set a=%%a
  5. )
  6. (for /f "tokens=1* delims=:" %%a in ('findstr /n "." 1.txt') do (
  7.      set "var=%%b"
  8.      setlocal enabledelayedexpansion
  9.     if %%a leq %a% (
  10.         echo;!var!
  11.      ) else if %%a geq %b% echo;!var!
  12.      endlocal
  13. ))>#.tmp
  14. move #.tmp 1.txt
  15. pause
复制代码

作者: smatenchen    时间: 2022-11-12 18:22

回复 28# terse BAT221110 qixiaobin0715 hfxiang idwma


1,
非常感谢!


2,
你的解法有用,不过解法有点复杂了。


我之前也想用行号法去解题,所以解法也搞得很复杂。


而其他大神们的解法,则是很轻巧,好似四两拨千斤。


用其他大神们的解法,较为好用。
还是不要用行号法了,行号法实在是复杂了一点。


3,
感谢大神们的帮忙!
作者: smatenchen    时间: 2022-11-12 21:54

本帖最后由 smatenchen 于 2022-11-13 10:12 编辑

回复 12# qixiaobin0715 terse BAT221110 hfxiang idwma Batcher
  1. @echo off
  2. (for /f "delims=" %%i in (1.txt) do (
  3.     if "%%i"=="[333]" set n=
  4.     if not defined n echo,%%i
  5.     if "%%i"=="[222]" set n=true
  6. ))>temp.log
  7. move temp.log 1.txt
复制代码



  1. if "%%~a"=="[333]" set /a b=1
  2. if !b! EQU 1 echo;%%a
  3. if "%%~a"=="[222]" set /a b=0
复制代码



1,
非常感谢!


2,
大神 qixiaobin0715 参考了第8楼大神 hfxiang 的解法,修改后写出的解法,
已知是最轻巧无bug的解法,了不起。


qixiaobin0715 和 hfxiang,两位大神,都非常了不起,尤其是大神 hfxiang,
没有 hfxiang 的珠玉解法在前,这道题难解得很。


大神 hfxiang,具有突破性创新思维,是难得的英才,实在是了不起。


3,
感谢大神们的帮忙!我再去调整组合一下,我的题就有解法了。
非常感谢!

作者: qixiaobin0715    时间: 2022-11-13 08:39

回复 30# smatenchen
你不会使用这个吗,看起来好别扭:
代码部分或文本示例使用 [code][/code] 标记括起来(单击回复框的 <> 按钮,复制粘贴代码进去),以便复制。
作者: smatenchen    时间: 2022-11-13 09:29

本帖最后由 smatenchen 于 2022-11-13 09:31 编辑

回复 31# qixiaobin0715 terse BAT221110 hfxiang idwma Batcher
  1. @echo off
  2. (for /f "delims=" %%i in (1.txt) do (
  3.     if "%%i"=="[333]" set n=
  4.     if not defined n echo,%%i
  5.     if "%%i"=="[222]" set n=true
  6. ))>temp.log
  7. move temp.log 1.txt
  8.    
复制代码
  
  1. if "%%~a"=="[333]" set /a b=1
  2. if !b! EQU 1 echo;%%a
  3. if "%%~a"=="[222]" set /a b=0
复制代码


1,
非常感谢!


2,
哦!好主意!
那是,插入代码功能。


有需要时,的确是应该使用它的,以方便复制代码。


3,
感谢大神们帮忙!
非常感谢!





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