windows 使用批处理脚本从文本文件中删除多行字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3279431/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:52:05  来源:igfitidea点击:

Remove multi-line strings from a text file using a batch script

windowsstringbatch-file

提问by Robert Davey

I am trying to create a batch file that will edit a text file to remove lines that contain a certain string andremove the line directly after that. An example of this file would look like this:

我试图创建一个批处理文件,将编辑一个文本文件中删除包含某个字符串的行直接后删除线。此文件的示例如下所示:

LINE ENTRY KEEP_1 BLA BLA
END
LINE ENTRY REMOVE_1 FOO BAR
END
LINE ENTRY REMOVE_2 HELLO WORLD
END
LINE ENTRY KEEP_2 CAT DOG
END

After running the batch script I require the new file to contain

运行批处理脚本后,我需要包含新文件

LINE ENTRY KEEP_1 BLA BLA
END
LINE ENTRY KEEP_2 CAT DOG
END

where any line containing REMOVE_ has been deleted, as well as the corresponding 'END' line.

其中包含 REMOVE_ 的任何行以及相应的“END”行都已被删除。

I have tried using the technique found hereto remove the lines containing the string but it does not appear to be possible to include characters such as \r\n to check for and include the 'END' in the search. I can't do this as 2 seperate FINDSTR commands as I still require the 'END' text to be kept for the other two entries.
Using findstr /v REMOVE_leaves me with the following:

我曾尝试使用此处找到的技术删除包含字符串的行,但似乎不可能包含诸如 \r\n 之类的字符来检查并在搜索中包含“END”。我不能将其作为 2 个单独的 FINDSTR 命令执行,因为我仍然需要为其他两个条目保留“END”文本。
使用findstr /v REMOVE_让我有以下几点:

LINE ENTRY KEEP_1 BLA BLA
END
END
END
LINE ENTRY KEEP_2 CAT DOG
END

and using findstr /v "REMOVE_*\r\nEnd"does not seem to work at all. Just to confirm each line is definitely terminated with \r\n.

并且使用findstr /v "REMOVE_*\r\nEnd"似乎根本不起作用。只是为了确认每一行肯定以\r\n.

Any help on this issue would be greatly appreciated.

对此问题的任何帮助将不胜感激。

回答by sakra

The following batch script should do what you want:

下面的批处理脚本应该做你想做的:

@echo off
setlocal enabledelayedexpansion

set /A REMOVE_COUNT=1

if "%~2"=="" (
    echo Usage: %~n0 search_str file
    echo remove lines that contain a search_str and remove %REMOVE_COUNT% line^(s^) directly after that
    exit /b 1
)

set "SEARCH_STR=%~1"
set "SRC_FILE=%~2"

set /A SKIP_COUNT=0
for /F "skip=2 delims=[] tokens=1,*" %%I in ('find /v /n "" "%SRC_FILE%"') do (
    if !SKIP_COUNT! EQU 0 (
        set SRC_LINE=%%J
        if defined SRC_LINE (
            if "!SRC_LINE:%SEARCH_STR%=!" == "!SRC_LINE!" (
                echo.!SRC_LINE!
            ) else (
                set /A SKIP_COUNT=%REMOVE_COUNT%
            )
        ) else (
            rem SRC_LINE is empty
            echo.
        )
    ) else (
        set /A SKIP_COUNT-=1
    )
)

The number of lines to be removed after a matched line can be configured by setting the REMOVE_COUNTvariable.

可以通过设置该REMOVE_COUNT变量来配置匹配行后要删除的行数。

The script also handles files with empty lines correctly by using a trick: The find command is used to prefix all lines with line numbers. That way the for command will not skip empty lines.

该脚本还通过使用一个技巧正确处理带有空行的文件: find 命令用于为所有行添加行号前缀。这样 for 命令就不会跳过空行。

回答by Joey

findstroperates line-wise. You cannot do anything with it that spans more than a single line.

findstr逐行操作。你不能用它做任何跨越单行的事情。

In any case, you're in for a world of pain if you do this with batch files. While you certainly canloop through the file and only output certain lines, this would look kinda like the following:

无论如何,如果您使用批处理文件执行此操作,您将陷入痛苦的世界。虽然您当然可以遍历文件并只输出某些行,但这看起来有点像以下内容:

set remove=
for /f %%x in (file.txt) do (
  if not defined remove (
    echo %%x|findstr "REMOVE" >nul 2>&1 && set remove=1
    if not defined remove echo.%%x
  ) else (
    set remove=
  )
)

(untested, but might work). The problem here is twofold: for /fremoves any empty lines from the output so if your file had them before you won't have them afterwards. This may or may not be a problem for your specific case. Another problem is that dealing with special characters can get hairy. I give no guarantee that the above works as it should for things like >, <, &, |, ...

(未经测试,但可能有效)。这里的问题是双重的:for /f从输出中删除任何空行,因此如果您的文件之前有空行,之后就不会再有空行了。对于您的特定情况,这可能是也可能不是问题。另一个问题是处理特殊字符可能会很麻烦。我不保证上述内容对于>, <, &, |, ...

Your best bet in this case, if you need to run it on almost any Windows machine, would probably be a VBScript. The string handling capabilities are much more robust there.

在这种情况下,如果您需要在几乎所有 Windows 机器上运行它,最好的选择可能是 VBScript。那里的字符串处理功能更加强大。