Board logo

标题: [文本处理] 批处理如何删除含A内容以上文本、及含B内容以下文本,保留中间的文本? [打印本页]

作者: kidzgy    时间: 2023-8-5 00:54     标题: 批处理如何删除含A内容以上文本、及含B内容以下文本,保留中间的文本?

本帖最后由 kidzgy 于 2023-8-5 21:03 编辑
  1. [删除的内容]
  2. [删除的内容]
  3. [删除的内容]
  4. Array.prototype.p = Array.prototype.push;   [本行也删除]
  5. [保留的内容]
  6. [保留的内容]
  7. [保留的内容]
  8. [保留的内容]
  9. [保留的内容]
  10. delete(Array.prototype.p);     [本行也删除]
  11. [删除的内容]
  12. [删除的内容]
  13. [删除的内容]
复制代码
须注意:【Array.prototype.p = Array.prototype.push; 】 【delete(Array.prototype.p); 】内容在全文搜索均仅有一个结果,如何删除【Array.prototype.p = Array.prototype.push; 】本行内容及以上的所有文本、【delete(Array.prototype.p); 】本行内容及以下的文本?且最终的效果是保留内容上下无空白行?

预期效果如下:
  1. [保留的内容]
  2. [保留的内容]
  3. [保留的内容]
  4. [保留的内容]
  5. [保留的内容]
复制代码
测试文件:
由于压缩包超过50KB,无法上传至此,故用外链。测试文件系由Snap2HTML生成的html文件。
https://wwi.lanzoup.com/iUDU114kcw4j


我刚刚灵光一闪,换了个思路,发现【findstr /i "D.p([" %1 > "temp.html"】这样的方法即可提取出所需的内容。
由于生成多个的html是可以拼接的,还是很好奇,如何运用开始的思路来分离文本?
作者: 77七    时间: 2023-8-5 01:31

  1. @echo off
  2. rem 注意将代码中的两处字符串替换为文本中的整行,包含行首、尾空格(如有)。
  3. (for /f "useback delims=" %%a in ("1.txt") do (
  4. if "%%a" equ "delete(Array.prototype.p);" (
  5. goto :next
  6. )
  7. if defined n (
  8. echo %%a
  9. )
  10. if "%%a" equ "Array.prototype.p = Array.prototype.push;" (
  11. set n=1
  12. )
  13. ))>"2.txt"
  14. :next
  15. pause
复制代码

作者: hfxiang    时间: 2023-8-5 09:24

回复 1# kidzgy
可试一下第3方工具sed ( http://bcn.bathome.net/tool/4.9/sed.exe )
  1. sed -n -r "/^Array\.prototype\.p = Array\.prototype\.push\;/,/^delete\(Array\.prototype\.p\)\;/{/^$/d;/^Array\.prototype\.p = Array\.prototype\.push\;/d;/^delete\(Array\.prototype\.p\)\;/d;p}" a.txt>b.txt
复制代码

作者: wanghan519    时间: 2023-8-5 09:56

sed删除1到Array那一行,再删除delete到最后一行,也许可以
  1. sed '1,/^Array/d;/^delete/,$d' a.txt
复制代码

作者: kidzgy    时间: 2023-8-5 13:53

77七 发表于 2023-8-5 01:31



   
回复  kidzgy
可试一下第3方工具sed (  )
hfxiang 发表于 2023-8-5 09:24



  两个输出都是空白文件
作者: 77七    时间: 2023-8-5 14:24

回复 5# kidzgy


   参考2楼代码第2行。
作者: Five66    时间: 2023-8-5 14:36

本帖最后由 Five66 于 2023-8-6 03:42 编辑

input.txt是输入文件名
output.txt是输出文件名
编码ascii
  1. @if (0)//==(0)// echo off&pause&cscript //nologo -e:jscript "%~f0"&pause&exit
  2. @end
  3. var inf,otf,sstr,estr,s,bbb;
  4. inf="input.txt";
  5. otf="output.txt";
  6. sstr="Array.prototype.p = Array.prototype.push;";
  7. estr="delete(Array.prototype.p);";
  8. var fso=new ActiveXObject('scripting.filesystemobject');
  9. inf=fso.OpenTextFile(inf,1,false);
  10. otf=fso.OpenTextFile(otf,2,true);
  11. s='';bbb=0;
  12. while(!inf.AtEndOfStream){
  13. s=inf.ReadLine();
  14. if(s==estr){break;}
  15. if(bbb && s){otf.WriteLine(s);s='';}
  16. if(s==sstr){bbb=1;}
  17. }
  18. inf.Close();otf.Close();fso=null;
复制代码

作者: aloha20200628    时间: 2023-8-5 16:49


用sed.exe(本坛第三方下载)确实比用纯P轻爽 》先粗洗一遍源文,再掐头去尾...
  1. @echo off
  2. set "p1=^Array.prototype.p = Array.prototype.push;$"
  3. set "p2=^delete(Array.prototype.p);"
  4. sed -n "/%p1%/, /%p2%/p" "源文件" | sed -e "/^$/d" -e "$d" -e "1d"
复制代码

作者: aloha20200628    时间: 2023-8-5 18:42


再给一个尽量简化的纯P版本,与近来数帖 '在界定行之间提取目标数据' 的题型均属同一套路...
  1. @echo off
  2. set "p1=Array.prototype.p = Array.prototype.push;"
  3. set "p2=delete(Array.prototype.p);"
  4. set "got="
  5. for /f "delims=" %%s in (源文件) do (
  6. if /i "%%s"=="%p1%" (set "got=1") else if defined got (
  7. if /i "%%s"=="%p2%" (exit/b) else (echo,%%s)
  8. )
  9. )
复制代码

作者: Batcher    时间: 2023-8-5 20:47

回复 1# kidzgy


    请把文件上传到网盘以便测试代码
作者: kidzgy    时间: 2023-8-5 21:00

回复 7# Five66


   

提示D:\Personal\Desktop\123.bat(19, 5) Microsoft JScript 运行时错误: 输入超出了文件尾


现在已在楼主层附上测试文件。
作者: jyswjjgdwtdtj    时间: 2023-8-5 21:16

  1. 'vbs
  2. set fso=createobject("scripting.filesystemobject")
  3. set r=new regexp
  4. sstr="Array.prototype.p = Array.prototype.push;"
  5. estr="delete(Array.prototype.p);"
  6. inf="input.txt";
  7. otf="output.txt";
  8. inf=fso.OpenTextFile(inf,1,false)
  9. otf=fso.OpenTextFile(otf,2,true)
  10. r.pattern=sstr&"(.*)"&estr
  11. r.multiline=true
  12. otf.write r.execute(inf.readall)(0).submatches(0)
复制代码
或许可以吧
作者: 77七    时间: 2023-8-5 23:17

test.html
  1. var D = dirs;
  2. Array.prototype.p = Array.prototype.push;
  3. D.p(["D:/quest2*0*1680711711*D:/quest2/","CastReceiver_1.5.6_armeabi-v7a_by_Prosmart.by.apk*12505115*1618494146","SKYBOX v1.1.0.465.apk*140533455*1680486331","SKYBOX VR Video Player [1.1.0.525].apk*121507878*1647912077","ssrray-release-3.8.10.1.apk*36174974*1621004286",310721422,"1"])
  4. D.p(["D:/quest2/adb*0*1633840967","aapt.exe*1639424*1619405894","aapt_20210426105805.exe*1639424*1619405894","adb.exe*1974272*1619405894","adb_20210426105805.exe*1974272*1619405895","AdbWinApi.dll*97792*1619405894","AdbWinApi_20210426105805.dll*97792*1619405894","AdbWinUsbApi.dll*62976*1619405894","AdbWinUsbApi_20210426105808.dll*62976*1619405895",7548928,""])
  5. delete(Array.prototype.p); // remove alias added above
  6. $(document).ready(function(){
复制代码


code2
  1. @echo off
  2. chcp 65001 >nul
  3. rem 批处理保存为utf-8编码格式
  4. set "str1=Array.prototype.p = Array.prototype.push;"
  5. set "str2=delete(Array.prototype.p);"
  6. for /f "tokens=1 delims=:" %%a in ('^<"test.html" findstr /n /c:"%str1%" /c:"%str2%"') do (
  7. if not defined s (
  8. set s=%%a
  9. ) else (
  10. set e=%%a
  11. )
  12. )
  13. (for /f "tokens=1* delims=:" %%a in ('^<"test.html" findstr /n .') do (
  14. if %%a gtr %s% if %%a lss %e% (
  15. echo=%%b
  16. )
  17. ))>"out.html"
复制代码

作者: kidzgy    时间: 2023-8-5 23:55

回复 13# 77七


   感谢解答,这个似乎有局限性,用楼主层的文件测试是没有问题的,因为处理的代码比较短,我用另外一个文件测试,会提示 FINDSTR: Line 772 is too long.

这个是新的测试文件:
https://wwi.lanzoup.com/imB4X14kr4kh
作者: kidzgy    时间: 2023-8-6 00:35

另外想请教个问题:
  1. gawk -v "IGNORECASE=1" "{print $0=gensub(/quest2/,\"xyz\",\"g\")>\"test.html\"}" test.html
复制代码
我用上述代码,读取文件和生成文件指向同一个文件的时候,会导致内容缺失。不知道是什么原因?我有时候修改其他文件的时候倒没有这个问题。




或许可以吧
jyswjjgdwtdtj 发表于 2023-8-5 21:16


vbs代码执行时弹错。
作者: Five66    时间: 2023-8-6 01:08

回复 11# kidzgy

呃,测试文件是utf-8 bom编码的,而且换行符是LF,试试下面的

test.html为输入文件名
output.txt为输出文件名,输出文件编码跟换行符都跟测试文件一样的
代码保存为ansi就行了
  1. #@&cls&pause&powershell "gc -literalpath '%~f0'|out-string|iex"&pause&exit
  2. $inf="test.html"
  3. $otf="output.txt"
  4. $sstr="Array.prototype.p = Array.prototype.push;"
  5. $estr="delete(Array.prototype.p);"
  6. $inf=[io.file]::OpenRead($pwd.path+"\$inf")
  7. $otf=[io.file]::OpenWrite($pwd.path+"\$otf")
  8. $infrd=[System.IO.StreamReader]::new($inf,[text.encoding]::UTF8)
  9. $otfwd=[System.IO.StreamWriter]::new($otf,[text.encoding]::UTF8)
  10. $otfwd.NewLine=("`n")
  11. $s='';$bbb=0;
  12. while(!$infrd.EndOfStream){
  13. $s=$infrd.ReadLine()
  14. if($s){
  15. $ss=$s.Trim()
  16. if(($ss.Length -ge $estr.Length) -and ($ss.SubString(0,$estr.Length) -eq $estr)){break;}
  17. if($bbb){$otfwd.WriteLine($s);$s='';}
  18. if(($ss.Length -ge $sstr.Length) -and ($ss.SubString(0,$sstr.Length) -eq $sstr)){$bbb=1;}
  19. }}
  20. $infrd.Close();$otfwd.Close()
复制代码

作者: wanghan519    时间: 2023-8-6 06:50

本帖最后由 wanghan519 于 2023-8-6 06:57 编辑

回复 15# kidzgy


    awk不能输入输出指向同一个文件,除非使用-i inplace参数或者使用sponge命令,但单文件的gawk没有这些。。。
sed可以用-i参数,用例子试了sed -i '1,/^[[:blank:]]*Array/d;/^[[:blank:]]*delete/,$d;/^$/d' test.html
作者: qixiaobin0715    时间: 2023-8-6 08:58

在cmd中无论是设置环境变量或是循环变量,其变量值都有限制。
楼主的文件直接用命令(比如type)显示没有问题,如果将其与变量建立联系,一旦超出长度限制,代码就会将其忽略。比如14楼提供的文件中的第99行,由于长度过长而超限,如果在for循环中读取,循环变量%%I就会将其忽略,而继续读取下一行。
所以不能考虑使用纯P来处理。
作者: aloha20200628    时间: 2023-8-6 10:11

回复 14# kidzgy

订正8L的代码如下,用14L提供的新测试文件验证成功。
  1. @echo off
  2. set "p1=Array.prototype.p = Array.prototype.push;"
  3. set "p2=delete(Array.prototype.p);"
  4. sed -n "/%p1%/, /%p2%/p" "test2.html" | sed -e "/^$/d" -e "$d" -e "1d">"test2.html.new"
复制代码

作者: kidzgy    时间: 2023-8-6 10:26

本帖最后由 kidzgy 于 2023-8-6 10:36 编辑

回复 17# wanghan519

在gawk使用 【-i inplace】参数时,即【gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' "test.html"】,会提示以下:
  1.     gawk: fatal: cannot open source file `inplace' for reading: No such file or directory
复制代码


不知道是哪里出了问题

更正:
不好意思,原来akw 和gawk不是同一个东西的嘛,所以如果要直接修改源文件的话,只能用sed -i 了?
作者: kidzgy    时间: 2023-8-6 10:37

回复 16# Five66

回复 19# aloha20200628

感谢两位,经测试,非常完美!
作者: aloha20200628    时间: 2023-8-6 11:11

针对LZ提供的测试文件,其实不用下载第三方,直接用下式
     findstr /LB "D.p(" "test2.html">"test2.html.new"
即可一步达成LZ所要结果(即使测试文件是utf-8编码,单行字符量远超8K) ... LZ是要求助有比其更'好'的方法吗? ...至今尚未看到...
作者: wanghan519    时间: 2023-8-6 12:13

回复 20# kidzgy


    单文件的gawk.exe好像得输出到临时文件再覆盖回去,git for windows里面的gawk就能用,装上也不亏毕竟git还是比较常用的。。。
作者: kidzgy    时间: 2023-8-6 12:49

回复 22# aloha20200628


    哈哈,其实我在楼主层末段已经说明了同样的方法。
作者: hfxiang    时间: 2023-8-6 13:10

回复 5# kidzgy

3楼的代码针对原1楼提供的测试样本测试是有效的。
现针对https://wwi.lanzoup.com/iUDU114kcw4j提供的测试样本,修改如下,经测试有效:
  1. sed -n -r "/Array\.prototype\.p = Array\.prototype\.push\;/,/delete\(Array\.prototype\.p\)\;/{/^$/d;/Array\.prototype\.p = Array\.prototype\.push\;/d;/delete\(Array\.prototype\.p\)\;/d;p}" test.html>b.txt
复制代码

作者: jyswjjgdwtdtj    时间: 2023-8-6 13:12

回复 15# kidzgy

你看到分号就删一下呗
作者: 77七    时间: 2023-8-6 17:10

本帖最后由 77七 于 2023-8-6 17:14 编辑

文本行超长,批处理处理不了。要是我自己用的话,可以用第三方工具,linex和cfile ,都可以通过行号打印超长文本行。
打印第100行及接下来的10行
type 1.txt|linex -l 100 -e 10
linex -l 100 -e 10 <1.txt >2.txt
打印第100-110行
cfile 100,110 1.txt >2.txt
大概是这样。




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