[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文本处理] [已解决]求助批处理用一个文件的内容替换另一个文件一整段内容

本帖最后由 hnfeng 于 2023-11-30 14:45 编辑

一个批处理里面有多个 标签(类似以 :abcd 开头以 goto :EOF 结尾),想使用第三方程序把另一个文件例如 NewTxt.txt 的全部内容替换到:abcdgoto :EOF 之间的内容

例如:用 NewTxt.txt 的内容替换下面全部蓝色字符
@echo off
xxxxxxx 多行批处理代码
xxxxxxx 多行批处理代码
call :abcd
xxxxxxx 多行批处理代码
xxxxxxx 多行批处理代码
exit

:abcd
xxxxxxx 多行批处理代码
xxxxxxx 多行批处理代码

goto :EOF

:xyz
xxxxxxx 多行批处理代码
xxxxxxx 多行批处理代码
goto :EOF


请高手帮忙指导,谢谢了
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2

回复 1# hnfeng


    考虑到众多特殊字符的问题,建议说说最根本的真实原因,也许有更便捷的实现方案。
测试代码之前请做好备份

TOP

本帖最后由 hnfeng 于 2023-11-30 09:03 编辑

回复 2# ShowCode


    需要替换的蓝色文字,其实是我的批处理里面用作设置变量的,格式全部是 set abc123=xxxxxxxxx
其中 xxxxxxxxx 可能含有 数字英文中文标点符号 !$()—-+【{}】;‘’:",。、《》TAB 等,如果有特殊符号不能使用,我可以不用

TOP

回复 1# hnfeng

用gawk( http://bcn.bathome.net/tool/5.1.0/gawk.exe )实现方法如下:
  1. gawk "/^:abcd$/,/^goto :EOF$/{if(/^:abcd$/){print;while((getline < \"NewTxt.txt\")>0){print}}if(/^goto :EOF$/)print;next}1" 1.bat>2.bat
复制代码
1

评分人数

TOP

  1. @echo off
  2. (for /f "skip=1 tokens=1* delims=]" %%i in ('find /v /n "" test.bat') do (
  3.     if "%%j"==":abcd" (
  4.         set n=true
  5.         echo,%%j
  6.         type NewTxt.txt
  7.     ) else if defined n (
  8.         if "%%j"=="goto :EOF" (
  9.             echo,%%j
  10.             set n=
  11.         )
  12.     ) else (
  13.         echo,%%j
  14. )
  15. ))>New-test.bat
  16. pause
复制代码

TOP

回复 4# hfxiang


    多谢多谢,非常好用

TOP


一楼想要的结果亦可尝试如下方案,如此不必文本替换了》仅供参考
一。若NewTxt.txt中内容皆为批处理代码,可改扩展名为 NewTxt.bat 或 NewTxt.cmd
二。其中的 set abc123=xxxxxxxxx 句式改为 set "abc123=xxxxxxxxx"  备注》即便用双引号包裹,也不要在赋值表达式中包含%!^<|>等批处理脚本内定的语义字符
三。一楼示例代码中先删除 :abcd 至 goto :EOF 段落,再将 call :abcd 改为 call NewTxt.bat,如此会使外部脚本中的 set "abc123=xxxxxxxxx" 句式被自动执行,变为当前脚本中相应的赋值变量

TOP

回复 7# aloha20200628


    您说的确实是一种不错的方法。

以前我也这样用过,但是后来发现,如果被调用的批处理开头有
mshta vbscript:CreateObject("Shell.Application"...............  或其他 VBS 那样以管理员身份运行 的命令时,可能会出错或有错误信息(可能因为主批处理已经有这些命令了,不能重复运行),所以此次没想到用这个方法。但是如果仅仅是变量赋值,就没这个问题了,行得通。

set 命令里添加引号比较麻烦(原始数据是从excel复制过来的),$% 这些肯定要用的(貌似也可以用), ^<|> 是不能使用的

谢谢指教

TOP

回复 8# hnfeng


在调试/排错或维护一个大型批处理脚本时,用call调用其他外部批处理脚本(子过程/子模块)是常用的方法之一,如果单独运行某个子脚本无误,则在主脚本中用call调用这个子脚本也应该ok。
顺便给个提示》mshta的ie引擎到ie11版就不再支持vbs代码了,若非要使用须在mshta脚本中的头标签中加注有关的版本设定,例如头标签中至少包含如下代码
      <head><meta http-equiv="x-ua-compatible" content="ie=11"></head>

TOP

本帖最后由 WHY 于 2023-12-1 11:17 编辑

另一种办法:
  1. gawk -v IGNORECASE=1 "NR==FNR{a[NR]=$0;next}!n{print}!n&&/^:abcd$/{for(i in a)print a[i];n=1}n&&/^goto :EOF$/{print;n=0}" NewTxt.txt 1.bat > 2.bat
复制代码
也练习下纯批
改一下,少一个endlocal
  1. @echo off
  2. for /f "delims=" %%i in ('findstr /n .* 1.bat') do (
  3.     set "s=%%i"
  4.     setlocal enabledelayedexpansion
  5.     set "s=!s:*:=!"
  6.     if not defined flag (
  7.         echo;!s!
  8.         if /i "!s!" == ":abcd" (
  9.             endlocal
  10.             type NewTxt.txt | find /v ""
  11.             set flag=1
  12.         ) else (
  13.             endlocal
  14.         )
  15.     ) else if /i "!s!" == "goto :EOF" (
  16.         echo;!s!
  17.         endlocal
  18.         set "flag="
  19.     )  else (
  20.         endlocal
  21.     )
  22. )
  23. pause
复制代码
Test.js
  1. var txtFileName = 'NewTxt.txt';  //txt文件名
  2. var batFileName = '1.bat';       //修改前bat文件名
  3. var dstFileName = '2.bat';       //修改后bat文件名
  4. var fso = new ActiveXObject('Scripting.FileSystemObject');
  5. var s1 = fso.OpenTextFile(txtFileName, 1).ReadAll();  //读txt文本内容
  6. var s2 = fso.OpenTextFile(batFileName, 1).ReadAll();  //读bat文本内容
  7. s1 = s1.replace(/(?!\r\n).$/, '$&\r\n');  //txt结尾添加回车换行
  8. s2 = s2.replace(/^(:abcd\r\n)(?:(?!goto :EOF)[\s\S])+(?=goto :EOF)/mi, '$1' + s1); //替换内容
  9. fso.OpenTextFile(dstFileName, 2, true).Write(s2);
  10. WSH.Echo('Done')
复制代码
1

评分人数

TOP

回复 10# WHY


    gawk 命令有效,试验成功

纯批处理的,与5楼那个一样,不成功。

gawk 就蛮好的,谢谢

TOP

回复 11# hnfeng


    "不成功" 是指脚本运行时出错,还是指脚本运行后结果不对?
能否把你需要修改的 1.bat 和 NewTxt.txt 放到网盘,我测试一下。

TOP

本帖最后由 hnfeng 于 2023-12-1 09:21 编辑

回复 12# WHY


    我看了看你的批处理代码,代码没问题,与 5 楼的代码一样,加行号的处理和使用 type 替换进来 NewTxt.txt 的内容的方法很巧妙,只是最后您忘记输出结果了

倒数第二行修改为  
)>>2.bat
就好了

赞一个

TOP

本帖最后由 hnfeng 于 2023-12-1 09:22 编辑

回复 5# qixiaobin0715


    代码也能成功完成,之前是我把 文件名 输错了,不好意思抱歉了

加行号的处理和使用 type 替换进来 NewTxt.txt 的内容的方法很巧妙

谢谢,赞一个

TOP

来一个gawk处理一楼的示例,简单的逻辑,
  1. gawk "/^:goto EOF$/{n=0}!n{print}/^:abcd$/{n=1;while((getline<\"NewTxt.txt\")>0)print;next}" 1.bat>2.bat
复制代码

TOP

返回列表