【问题标题】:Batch script for search & replace without skipping empty line, '!' and ';'?用于搜索和替换而不跳过空行的批处理脚本,'!'和 ';'?
【发布时间】:2017-05-09 11:38:14
【问题描述】:

抱歉,第 (n+1) 次打扰您使用批处理脚本进行搜索和替换。 我有文本文件(实际上是 PS 文件)(大约 10kB-3MB),我只需要替换几个数字。

这应该很容易,我想。 我在 Stackoverflow 上发现了很多脚本,但到目前为止它们都没有正常工作。如果我忽略了“工作中的人”,请告诉我。

我尝试的最后一个:

@echo off
setlocal DisableDelayedExpansion
set OutputFile=%1
set OutputFile=%OutputFile:"=%
set InputFile=%OutputFile%.tmp

set SearchString=636170656C6C6133
set ReplaceString=636170656C6C6134

rem write empty file
type NUL > %OutputFile%

for /f "tokens=1,* delims=¶" %%A in ( '"type %InputFile%"') do (
 SET string=%%A
 setlocal EnableDelayedExpansion
 SET modified=!string:%SearchString%=%ReplaceString%!

 echo !modified!>>%OutputFile% 
 endlocal
)
del %InputFile%

首先,它似乎很慢(!)。我可以在磁盘上看到文件大小如何增加。 数字的出现似乎被替换了。但是,文件被更改了,我很容易从不同的文件大小中看出这一点。据我所知,空行、感叹号和以分号开头的行被跳过。这完全弄乱了我的文件。 如何避免这种情况? 如果我用 Perl 做同样的事情,我真的只改变了数字,没有别的。但是,我不想也不能使用 Perl。我也不想使用其他额外的程序或 Windows-Powershell,因为它也应该在旧系统上工作。 有没有办法用一个简单的 Windows 批处理脚本来实现这一点? 谢谢!

【问题讨论】:

  • 您遇到的问题是批处理解决方案所固有的。它们可能会被适合您的输入文件的解决方案克服,但您没有对此进行扩展。我认为批处理中的 j-/vbscript 可以帮助您。见jrepl.bat from dbenham on dostips.com
  • 感谢@LotPings,所以我知道使用简单的批处理脚本是不可能的,对吗?也许可以通过首先更改文件来完成,即屏蔽'!'';' 或添加例如'#' 在每一行的开头,然后再减去它?如果可能的话,我想避免使用 javascript、vbs-script 等。
  • 可以通过使用 find/findstring 对行进行编号来克服空行,! 使用 sub 或伪调用而不是 setlocal enabledelayedexpansion ; 定义不同的 eol char 但是这一切都不会加快执行速度。
  • 您是否尝试使用以下代码集从文件名中去除环绕引号:set OutputFile=%OutputFile:"=%。你就这样吧。 set OutputFile=%~1
  • @Squashman,基本上是的。如果有更优雅的方式,他们是受欢迎的。又学到东西了。谢谢!

标签: windows batch-file search replace


【解决方案1】:

VBS 脚本

Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
    Text = Inp.readall
    Text = Replace(Text, "636170656C6C6133", "636170656C6C6134")
    outp.write Text

使用

cscript //nologo script.vbs < input.txt > Output.txt

您使用正确的工具来完成这项工作。批处理用于启动程序和复制文件。

以上内容适合给定的文件大小。但是,如果我们要达到 100 多 MB,那么这段代码会更好。

Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
Do Until Inp.AtEndOfStream
    Text = Inp.readline
    Text = Replace(Text, "636170656C6C6133", "636170656C6C6134")
    outp.writeline Text
Loop

【讨论】:

    【解决方案2】:

    我相信以下是一个有效的 bat 脚本,除了所需的数字更改之外不应进行任何更改:

    @echo off
    setlocal DisableDelayedExpansion
    set "out=%~1"
    set "in=%out%.tmp"
    
    set "find=636170656C6C6133"
    set "repl=636170656C6C6134"
    
    >"%out%" (
      for /f "delims=" %%A in ('findstr /n "^" "%in%"') do (
        set "str=%%A"
        setlocal EnableDelayedExpansion
        set "str=!str:*:=!"
        if defined str set "str=!str:%find%=%repl%!"
        echo(!str!
        endlocal
      )
    )
    del "%in%"
    

    我所做的更改:

    • 使用%~1 删除括号。尽管从技术上讲,这不是必需的。像echo test &gt;"someName.txt".new 这样的东西就可以了。
    • FOR /F 去除空行。我使用 FINDSTR 在每行前面加上行号,后跟一个冒号。现在没有空行了。
    • 我使用* 的额外变量扩展查找/替换来删除行号前缀。
    • 如果字符串为空(未定义的变量),变量扩展查找/替换将失败。因此,我在查找/替换之前验证了变量是否已定义。
    • 回显空行或仅包含空格的行将导致ECHO is off. 输出。这可以通过使用echo( 解决
    • 初始化重定向需要时间,而且您的循环每次迭代都会执行此操作,这会减慢速度。我通过将整个 FOR 循环括在括号中并仅重定向一次来提高性能。

    由于以下任何原因,您仍然可能会看到文件大小略有变化

    • 如果输入有 \n 行终止符而不是 \r\n。
    • 如果输入的最后一行没有被 \r\n 终止。该脚本以 \r\n 结束所有行,无论输入是什么。

    如果任何行包含空字节,或者任何行的长度 >~8k,则脚本将失败。

    我讨厌使用批处理编辑文本文件 - 这是复杂的代码,速度很慢,而且即使是最好的解决方案仍然有很大的局限性。

    我建议您使用JREPL.BAT - a command line regular expression text processing utility。 JREPL 是纯脚本(混合批处理/JScript),可以在 XP 以后的任何 Windows 机器上本地运行 - 不需要第 3 方 exe 文件或特殊配置。

    该工具非常强大,有很多选项。完整的文档可通过命令行通过jrepl /?jrepl /?? 获得分页帮助。

    使用 JREPL 解决您的问题是微不足道的 - 您甚至不需要其他脚本。以下命令将直接在命令提示符下运行:

    jrepl 636170656C6C6133 636170656C6C6134 /f input.txt /o output.txt
    

    如果您将命令放在另一个批处理脚本中,请使用 CALL JREPL。

    JREPL 比解决这个简单问题所需的功能强大得多。但它非常方便,一旦你有了这个实用程序,我怀疑你会发现它有很多用途。特别是如果您学习使用正则表达式以及许多 JREPL 选项。

    【讨论】:

    • 感谢您提供详细而清晰的答案。我一直在想:一定有更好的方法我只是没有看到。如果您作为专家说这实际上很难,我真的不应该进一步尝试并寻找替代方案。幸运的是,我注意到创建输出的程序已经在使用 Python,所以我和其他人不会有额外的安装。第一个 python 脚本已经在工作了:-)。虽然答案不是我所希望的,但它清楚地解释并告诉我,我最好寻求另一种解决方案。因此,+1 和我必须接受的“解决方案”。谢谢!
    • 其实我还是测试了你的脚本。如果您将第 4 行更改为:set "in=%out%.tmp" 它可以工作并且速度也更快。再一次非常感谢你!在我的例子中,输入文件与刚刚添加的输出文件具有相同的名称 .tmp 这样我就可以避免稍后重命名,因为它是在 SO 上使用其他脚本完成的。
    • @theozh - 是的,这是一个由未经测试的代码导致的愚蠢错字,已全部修复。你真的应该看看JREPL.BAT。它完全满足您在旧机器上工作的需求。它比任何纯批处理解决方案都要快得多。所有版本的 Windows 都原生支持嵌入式 JScript,开箱即用。
    猜你喜欢
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多