搜索和批处理的批处理脚本替换而不跳过空行,'!'和';'?

时间:2016-12-23 19:32:37

标签: windows batch-file search replace

对不起,打扰你第(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批处理脚本实现这一目的? 谢谢!

2 个答案:

答案 0 :(得分:2)

我认为以下是一个有效的蝙蝠脚本,除了所需的数字更改外,不应进行任何更改:

@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 >"someName.txt".new这样的东西就可以了。
  • FOR / F剥去空行。我使用FINDSTR为每行添加行号,后跟冒号。现在没有空行。
  • 我使用额外的变量扩展查找/替换*来删除行号前缀。
  • 如果字符串为空(未定义变量),则变量扩展查找/替换将失败。所以我在执行find / replace之前验证了变量。
  • ECHOing一个空行或仅包含空格的行将导致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),可以在任何Windows机器上从XP开始本地运行 - 不需要第三方exe文件或特殊配置。

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

使用JREPL解决您的问题是微不足道的 - 您甚至不需要另一个脚本。以下命令可以在命令提示符下使用:

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

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

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

答案 1 :(得分:0)

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