【问题标题】:How to replace substrings in windows batch file如何替换Windows批处理文件中的子字符串
【发布时间】:2011-07-13 12:51:27
【问题描述】:

谁能告诉我在 Windows 中使用批处理文件...如何从文件中读取并替换 string=bath from file contains=bath Abath Bbath XYZbathABC with string hello 这样输出就像hello Ahello Bhello XYZhelloABC

【问题讨论】:

    标签: batch-file


    【解决方案1】:

    Andriy M 扩展,是的,您可以从一个文件中执行此操作,甚至是一个包含多行的文件

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    set "INTEXTFILE=test.txt"
    set "OUTTEXTFILE=test_out.txt"
    set "SEARCHTEXT=bath"
    set "REPLACETEXT=hello"
    
    for /f "delims=" %%A in ('type "%INTEXTFILE%"') do (
        set "string=%%A"
        set "modified=!string:%SEARCHTEXT%=%REPLACETEXT%!"
        echo !modified!>>"%OUTTEXTFILE%"
    )
    
    del "%INTEXTFILE%"
    rename "%OUTTEXTFILE%" "%INTEXTFILE%"
    endlocal
    

    编辑

    感谢 David Nelson,我已更新脚本,使其不再具有硬编码值。

    【讨论】:

    • 它很好并且可以工作,但由于某种原因它确实删除了空白行。 Gonzalezea 在以下链接的回答修复了空行剥离问题:stackoverflow.com/a/20227248/280109
    • 为考虑使用代码的读者提供一些信息:FOR 忽略空行,并且此代码还包含以 ; 开头的行,因为它是选项 eol 的默认值.由于此代码需要启用延迟扩展,因此此代码无法正确处理具有一个或多个 ! 的行。 ECHO 在环境变量modified 被删除的情况下输出echo is off.,因为替换字符串是空字符串并且搜索字符串匹配整行。搜索字符串不能包含等号,因为= 在替换表达式中有特殊含义。
    • 如果我需要更改两个单独的字符串,比如使用另一个 set "modified1=...,这段代码会有很大不同吗?
    • 哇,这么简单的事情似乎有点过头了。
    【解决方案2】:
    SET string=bath Abath Bbath XYZbathABC
    SET modified=%string:bath=hello%
    ECHO %string%
    ECHO %modified%
    

    编辑

    起初并没有看到您希望在替换之前先从文件中读取字符串。

    嗯,对于批处理文件,您没有太多处理文件的便利。在这种特殊情况下,您必须读取一行,执行替换,然后输出修改后的行,然后……然后呢?如果您需要替换所有文件中所有出现的“bath”,那么您将不得不使用循环:

    @ECHO OFF
    SETLOCAL DISABLEDELAYEDEXPANSION
    FOR /F %%L IN (file.txt) DO (
      SET "line=%%L"
      SETLOCAL ENABLEDELAYEDEXPANSION
      ECHO !line:bath=hello!
      ENDLOCAL
    )
    ENDLOCAL
    

    您可以向文件添加重定向:

      ECHO !line:bath=hello!>>file2.txt
    

    或者您可以将重定向应用到批处理文件。它必须是一个不同的文件。

    编辑 2

    添加了延迟扩展的适当切换,以正确处理具有批处理脚本语法的特殊含义的某些字符,例如!^ 等。 (谢谢,jeb!)

    【讨论】:

    • 好的,所以至少对于一个字符串,Windows 批处理功能是可能的(与 DOS 批处理或旧 Windows 版本不兼容)。但如果这适用于文件(尤其是多行文件),我会感到惊讶。
    • @schnaader:有可能,试试看Batch FindAndReplace
    • @jeb:好的,至少有可能,感谢您的链接。无论如何,我的回答中的“非常复杂”和“不兼容”都适用于此。
    • @schnaader:一般来说,它不像其他一些脚本工具那样优雅。我怀疑,最初它们被称为 batch 文件只是意味着 batch execution (命令)。但我可能错了。不管怎样,有cscriptPowerShell 在那里,我有时认为如果不是因为在整个Windows 领域可能仍在使用的大量脚本,他们会完全废弃批处理文件。
    • @Andriy M:在内容中使用!^ 可以改进它的安全性,并打开和关闭延迟扩展,例如Improved BatchSubstitute
    【解决方案3】:

    为了避免空行跳过(在 conf 文件中提供可读性),我将 aflat 和 jeb 答案 (here) 组合成如下内容:

    @echo off
    setlocal enabledelayedexpansion
    set INTEXTFILE=test.txt
    set OUTTEXTFILE=test_out.txt
    set SEARCHTEXT=bath
    set REPLACETEXT=hello
    set OUTPUTLINE=
    
    for /f "tokens=1,* delims=¶" %%A in ( '"findstr /n ^^ %INTEXTFILE%"') do (
       SET string=%%A
       for /f "delims=: tokens=1,*" %%a in ("!string!") do set "string=%%b"
       if  "!string!" == "" (
           echo.>>%OUTTEXTFILE%
       ) else (
          SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%!
          echo !modified! >> %OUTTEXTFILE%
      )
    )
    del %INTEXTFILE%
    rename %OUTTEXTFILE% %INTEXTFILE%
    

    【讨论】:

    【解决方案4】:

    为避免批处理解析器出现问题(例如感叹号),请查看Problem with search and replace batch file

    aflat的脚本修改后会包含感叹号等特殊字符。

    @echo off
    setlocal DisableDelayedExpansion
    set INTEXTFILE=test.txt
    set OUTTEXTFILE=test_out.txt
    set SEARCHTEXT=bath
    set REPLACETEXT=hello
    set OUTPUTLINE=
    
    for /f "tokens=1,* delims=¶" %%A in ( '"type %INTEXTFILE%"') do (
        SET string=%%A
        setlocal EnableDelayedExpansion
        SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%!
    
        >> %OUTTEXTFILE% echo(!modified!
        endlocal
    )
    del %INTEXTFILE%
    rename %OUTTEXTFILE% %INTEXTFILE%
    

    【讨论】:

      【解决方案5】:

      我为此做了一个函数,你只需要在批处理程序中调用它就可以了。

      工作原理与其他基本相同,因为这是最好的方法。
      Here's the link where I have that function

      【讨论】:

        【解决方案6】:

        为了避免空行跳过,只需替换这个:

        echo !modified! >> %OUTTEXTFILE%
        

        用这个:

        echo.!modified! >> %OUTTEXTFILE%
        

        【讨论】:

        • 这不是问题的答案
        【解决方案7】:

        如果你有Ruby for Windows

        C:\>more file
        bath Abath Bbath XYZbathABC
        
        C:\>ruby -pne "$_.gsub!(/bath/,\"hello\")" file
        hello Ahello Bhello XYZhelloABC
        

        【讨论】:

          猜你喜欢
          • 2011-02-15
          • 1970-01-01
          • 2014-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-05
          相关资源
          最近更新 更多