找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 25753|回复: 9

[文本处理] 批处理怎样删除TXT的最后一行到倒数的第n行, 并替換原文件?

[复制链接]
发表于 2024-3-14 15:19:00 | 显示全部楼层 |阅读模式
删除文件夹下所有TXT的最后一行到倒数的第n行, 并替換原文件.
已知, 正数删除从第1行至n行的代码如下:

那么, 如果要倒数删除最后一行至倒数第N行, 那么应当如何编写?

如果不从第一行计, 而从第S行起, 至第P行呢? 包括正数及倒数. 谢谢.
  1. @ECHO OFF
  2. SET TxtDir="%~dp0"
  3. echo.&set /p N=Please type in the end row No. (from 1 to this row, will be deleted!):

  4. CD /D %TxtDir%
  5. FOR /F "tokens=1 delims=" %%I IN ('DIR /A /B *.txt') DO ((MORE +%N% "%%I">"%%I_")&(DEL /A /F /Q "%%I")&(REN "%%I_" "%%I"))
  6. PAUSE
复制代码
发表于 2024-3-14 17:24:51 | 显示全部楼层
先获取总行数
再计算删除后需要输出的行数
最后输出所需的行数
发表于 2024-3-14 17:37:01 | 显示全部楼层
本帖最后由 77七 于 2024-3-14 17:41 编辑
  1. @echo off
  2. cd /d "%~dp0"
  3. set /a b=-2,d=-2
  4. for %%i in (*.txt) do (
  5.         setlocal
  6.         call :1 "%%i"
  7.         endlocal
  8. )
  9. pause & exit

  10.         :1
  11.         for /f "delims=" %%a in ('find /c /v "" ^<"%~1"') do (
  12.                 echo %%a
  13.                 set n=%%a
  14.         )
  15.         if %b% gtr 0 (
  16.                 if %d% gtr 0 (
  17.                         set /a s=b,e=b+d-1
  18.                 ) else (
  19.                         set /a s=b+d+1,e=b
  20.                 )
  21.         ) else (
  22.                 if %d% gtr 0 (
  23.                         set /a s=n+b+1,e=s+d-1
  24.                 ) else (
  25.                         set /a s=n+b+d+2,e=n+b+1
  26.                 )
  27.         )
  28.         echo 删除第 %s% - %e% 行
  29.         (for /f "tokens=1* delims=[]" %%a in ('find /n /v "" ^<"%~1"') do (
  30.                 if %%a lss %s% (
  31.                         echo=%%b
  32.                 ) else if %%a gtr %e% (
  33.                         echo=%%b
  34.                 )
  35.         ))>$
  36.         move $ "%~1"
  37.         exit /b

复制代码
b 为开始行,d 为删除行数,都可以为正、负数
发表于 2024-3-14 20:07:18 | 显示全部楼层
回复 1# xinghua_wei

可用第3方工具sed( http://bcn.bathome.net/tool/4.9/sed.exe )删除当前目录下所有txt文件的最后10(可自行修改)行后写回原文件的脚本如下:

  1. sed -i -n -e :a -e "1,10!{P;N;D;};N;ba" *.txt
复制代码
发表于 2024-3-14 20:13:01 | 显示全部楼层
回复 1# xinghua_wei
删除当前目录下所有txt文件的第3~10(可自行修改)行后写回原文件的脚本如下:

  1. sed -i "3,10d" *.txt
复制代码
发表于 2024-3-15 22:11:53 | 显示全部楼层
本帖最后由 aloha20200628 于 2024-3-16 09:08 编辑


截取文件中第n1至n2行的纯P老话题,似乎并无完解。
开启变量延迟+for/f skip参数,虽然效率不错,但会拦截文件中的!字符相关字段;
关闭变量延迟而借助find/findstr加注文本行序号的方法也会丢失文件中的[]字符或:字符。
还是给一个用纯P包装jscript代码的批处理脚本更便于使用,没有纯P的诸端限制,而且因采用字符集437后竟可通吃多种常见编码文件,使输出文件自动保持与输入文件编码一致...
以下代码存为test.bat运行
命令行调用参数》test.bat "源文件路径文件名" 起始行号 终止行号
生成结果文件 = "源文件路径文件名.new"

  1. @set @v=1 //&if "%~3" neq "" cscript /e:jscript "%~f0" "%~1" %2 %3 &exit/b
  2. v = WSH.arguments, as = WSH.createobject('adodb.stream');
  3. as.mode=3, as.type=2, as.charset='437', as.open, as.loadfromfile(v(0));
  4. alllines = as.readtext().split('\r\n'), as.close;
  5. nb = (v(1)<1)? 1: v(1), ne = (v(2)>=alllines.length)? alllines.length: v(2);
  6. if (nb>ne) WSH.quit();
  7. alllines = alllines.slice(nb-1,ne);
  8. as.open, as.writetext(alllines.join('\r\n')), as.savetofile(v(0)+'.new',2), as.close;
  9. WSH.quit();
复制代码

评分

参与人数 1技术 +1 收起 理由
77七 + 1 感谢分享

查看全部评分

发表于 2024-3-16 07:01:42 | 显示全部楼层
本帖最后由 wanghan519 于 2024-3-16 10:39 编辑

sed不方便倒数,但更原始的ed脚本可以方便的倒数
一直以为ed是过时的,后来发现git、diff都在用ed脚本,相比sed确实有一些好处

ed -s a.txt <<'EOF'
2,3d
$-2,$d
w
EOF
# 删除2到3,倒数第3到最后一行
发表于 2024-3-16 10:46:11 | 显示全部楼层
回复 3# 77七


   修改30-36行代码,解决行首出现”[“ ”]“丢失问题
  1. (for /f "delims=" %%a in ('find /n /v "" ^<"%~1"') do (
  2.         set str=%%a
  3.         setlocal enabledelayedexpansion
  4.         if %%a lss %s% (
  5.                 echo=!str:*]=!
  6.         ) else if %%a gtr %e% (
  7.                 echo=!str:*]=!
  8.         )
  9.         endlocal
  10. ))>$
复制代码
发表于 2024-3-16 13:09:15 | 显示全部楼层

6楼代码用于 '截取' n1-n2区间行,是掐头去尾取中段,test.bat应更名为 "取中段.bat"
再给一段代码用于 '删除' n1-n2区间行,是留头留尾去中段,test.bat可取名为 "去中段.bat" ,命令行用法如同6楼命令行参数
jscript代码中弃用splice()方法是因其低效,还不如用slice()+concat()
再复课一遍》因采用437字符集编码,可不必在批处理脚本中特别打理与源文件编码对应的chcp...码页切换,用一个“437”即可通吃ansi/utf-8/utf-8+BOM/gbk/gb2312/...

  1. @set @v=1 //&if "%~3" neq "" cscript /e:jscript "%~f0" "%~1" %2 %3 &exit/b
  2. v = WSH.arguments, as = WSH.createobject('adodb.stream');
  3. as.mode=3, as.type=2, as.charset='437', as.open, as.loadfromfile(v(0));
  4. alllines = as.readtext().split('\r\n'), as.close;
  5. nb = (v(1)<1)? 1: v(1), ne = (v(2)>=alllines.length)? alllines.length: v(2);
  6. if (nb>ne) WSH.quit();
  7. for (; alllines.slice(-1)==''; alllines.pop());
  8. ab = alllines.slice(0, nb-1), ae = alllines.slice(ne), alllines = ab.concat(ae);
  9. as.open, as.writetext(alllines.join('\r\n'));
  10. as.savetofile(v(0)+'.new',2), as.close; WSH.quit();
复制代码
发表于 2024-3-16 13:21:39 | 显示全部楼层
本帖最后由 aloha20200628 于 2024-3-16 13:32 编辑


补缺》采用437字符集编码的优势有一个前提,是限于处理文件中的单字节ascii字符,其有效用法例如删除utf-8+BOM编码文件头标,删除文件尾部空行...
虽然adodb.stream可以二进制方式直接处理字节数据,但要比处理字符串麻烦,尤其是启用正则匹配...
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-18 05:25 , Processed in 0.013099 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表