使用批处理语言查找文本并将其替换为txt

时间:2018-07-10 17:49:37

标签: windows batch-file

我的代码有问题...
我有文件t1.txt和t2.txt。目标是将具有相同内容的文件1移到文件2,除非它包含特定的单词,在这种情况下,必须用预定义的单词替换整行。

具体地说,我对'if'和变量的重新分配有疑问。

@echo off
setlocal enabledelayedexpansion
set p1=t1.txt
set p2=t2.txt
for /f "tokens=*" %%a in (%p1%) do (
    set nl=%%a
    if not "%n1%"=="%n1:texto=%" (
        set n1=replace with this text
    )
    echo !n1! >> %p2%
)
pause>nul
exit

2 个答案:

答案 0 :(得分:1)

使用纯批处理脚本可以完成您的任务,但是对于某些特殊字符并且不丢失原始文件的空行,以安全的方式进行任务并不是那么简单。所以这是一种方法:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_IFILE=t1.txt"   & rem // (input file to be processed)
set "_OFILE=t2.txt"   & rem // (output file to be returned)
set "_WORD=\<texto\>" & rem // (string to search in lines, `findstr` regular expression)
set "_REPL=replace with this text" & rem // (text to replace lines containing the word)

rem // Output to console if no output file is provided:
if not defined _OFILE set "_OFILE=con"
rem /* Initialise a loop counter which should be synchronous to the line number, unless
rem    a line matches the search string, so it becomes skipped and the numbers differ: */
set /A "LCNT=0"
rem // Write to output file:
> "%_OFILE%" (
    rem /* Read from input file, prefix every line by a line number + `:`, skip lines
    rem    matching the search string: */
    for /F delims^=^ eol^= %%L in ('cmd /V /C findstr /V /N /R /C:"!_WORD!" "!_IFILE!"') do (
        rem // Split off the line number from the line string:
        for /F "delims=:" %%K in ("%%L") do (
            rem // Increment loop counter:
            set /A "LCNT+=1"
            rem // Store current line (including line number prefix):
            set "LINE=%%L"
            rem // Toggle delayed expansion in order to avoid trouble with `!`:
            setlocal EnableDelayedExpansion
            rem // Check whether loop counter and line number differ:
            if !LCNT! lss %%K (
                rem /* Numbers differ, hence return the replace line as many times
                rem    as the difference is: */
                set /A "DIFF=%%K-LCNT"
                for /L %%D in (1,1,!DIFF!) do echo(!_REPL!
            )
            rem // Return line with line number prefix removed:
            echo(!LINE:*:=!
            endlocal
            rem // Synchronise loop counter with line number:
            set "LCNT=%%K"
        )
    )
)

endlocal
exit /B

限制:

  • 行的长度不得超过8190个字符(受for /Fvariable长度的限制);
  • 搜索表达式不能超过254个字符(受findstr限制);
  • 输入文本文件必须为ASCII / ANSI编码(cmd可能会错误地处理其他文件,具体取决于当前的code page);
  • 输入文本文件中不应包含代码高于0x7F的字符(cmd可能会将这些字符更改为其他字符,具体取决于当前代码页);
  • 输入文本文件必须具有DOS / Windows样式的行尾(可以理解Unix样式的行尾,但是输出文本文件将具有DOS / Windows样式的行尾;而MAC样式的行尾则不完全受支持);

答案 1 :(得分:0)

命令 FOR 始终忽略空行,默认情况下,它也忽略以分号开头的行。在使用延迟扩展时,还会在循环中执行命令行set nl=%%a时修改包含感叹号的行。因此,根据文件t1.txt的内容,使用 FOR 的解决方案可能是完全错误的尝试。

下载由 Dave Benham 编写的JREPL.BAT,这是一个批处理文件/ JScript混合程序,可使用JScript在文件上运行正则表达式替换并将其存储在与以下批处理文件相同的目录中

@echo off
if not exist "%~dp0jrepl.bat" goto :EOF
if not exist "t1.txt" goto :EOF

call "%~dp0jrepl.bat" "^.*textto.*$" "replace with this text" /F "t1.txt" /O "t2.txt"

rem Compare the two files binary with ignoring the differences. Delete file
rem t1.txt if a line was modified by JREPL.BAT. Otherwise move file t1.txt
rem over t2.txt to keep the last modification date of file t1.txt for t2.txt.
%SystemRoot%\System32\fc.exe /B "t1.txt" "t2.txt" >nul
if errorlevel 1 ( del "t1.txt" ) else move /Y "t1.txt" "t2.txt"

jrepl.bat使用正则表达式搜索包含textto的行,并将所有这些行替换为replace with this text。将所有其他行从输入文件t1.txt未经修改地复制到输出文件t2.txt

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • call /?
  • del /?
  • echo /?
  • fc /?
  • goto /?
  • if /?
  • move /?
  • rem /?
  • jrepl.bat /?