使用批处理基于多个条件删除delim之间的文本

时间:2014-03-03 16:10:52

标签: batch-file

我正在尝试从垂直报告中删除看起来像这样的条目。

report start : hi good morning
report (1234) hi
10/10/2013
line unequal
good morning hi good morning (123:)
20131212020202312312********
report start : hi good evening
report (1234) hi
10/10/2013
good evening hi good evening (123:)
20131212020202312312********
report start : hi good morning
report (1234) hi
10/10/2013
good evening hi good evening (123:)
20131212020202312312********

我正在尝试删除“晚上”存在且“早晨”不存在的完整条目。简而言之,报告应该像这样结束:

report start : hi good morning
report (1234) hi
10/10/2013
line unequal
good morning hi good morning (123:)
20131212020202312312********
report start : hi good morning
report (1234) hi
10/10/2013
good evening hi good evening (123:)
20131212020202312312********

我曾在“ * * ”之间连接所有内容,其中每一行都以系列星号结束。它们的长度始终相同。然后使用findstr删除条目,但如何重建整个报告?它必须返回垂直格式。为了增加复杂性,结果在txt文件中有各种缩进。

我无法使用“ * ”作为delim,因此无法引入for / f循环进行连接。这是我走了多远。

由于

4 个答案:

答案 0 :(得分:1)

@ECHO OFF
SETLOCAL
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")
:: Process file, count sections and record section numbers to remove
SET /a section=0
CALL :init
FOR /f "delims=" %%a IN (q22151608.txt) DO (
ECHO %%a|FINDSTR "evening" >NUL
 IF NOT ERRORLEVEL 1 SET found1=Y
ECHO %%a|FINDSTR "morning" >NUL
 IF NOT ERRORLEVEL 1 SET found2=Y
 ECHO %%a|FINDSTR /e "********" >NUL
 IF NOT ERRORLEVEL 1 CALL :endsection
)
:: Re-process file, count sections
SET /a section=0
CALL :init
(
FOR /f "delims=" %%a IN (q22151608.txt) DO (
 IF NOT DEFINED found1 CALL :switch
 IF DEFINED found2 ECHO(%%a
 ECHO %%a|FINDSTR /e "********" >NUL
 IF NOT ERRORLEVEL 1 CALL :init
)
)>newfile.txt
DEL "%tempfile%a"

GOTO :EOF

:switch
SET found1=Y
FIND "#%section%#" "%tempfile%a" >NUL
IF ERRORLEVEL 1 SET found2=Y
GOTO :eof

:endsection
IF DEFINED found1 IF NOT DEFINED found2 >>"%tempfile%a" ECHO(#%section%#
:init
SET "found1="
SET "found2="
SET /a section+=1
GOTO :eof

我使用了一个名为q22151608.txt的文件,其中包含我的测试数据。输出是文件newfile.txt

您的输出说明不适合您的问题定义。如果我已正确解释您的描述,则不应出现line unequal行。

最好发布适当审查的实际数据而不是人工数据。部分的开始和结束位置尚不清楚。即使像更改报告的时间戳数这样简单的事情也会使提供的数据更加清晰。

答案 1 :(得分:1)

正则表达式可以是你的朋友:)像awk或sed这样的工具可以很好地工作 - 免费的Windows端口可用。

我写了REPL.BAT - a hybrid JScript/batch utility执行正则表达式搜索并替换stdin并将结果写入stdout。它是纯脚本,可​​以在任何Windows机器上从XP开始本地运行。完整的文档嵌入在脚本中。

假设REPL.BAT位于您当前的目录中,或者更好,位于PATH中的某个位置,那么您只需要以下内容:

type source.txt|repl "^report start :(?:[\s\S](?!morning))*?evening(?:[\s\S](?!morning))*?^\d*\*{8}\r?\n" "" m >output.txt

以上使用M选项启用多行搜索,这需要将整个源文件加载到内存中。对于非常大的输入文件,这可能会成为问题。但这仍然比使用FOR / F的纯批处理解决方案更好,因为该命令还将整个源文件缓冲在内存中。

答案 2 :(得分:0)

@echo off
setlocal EnableDelayedExpansion

set i=0
set "morning="
set "evening="
for /F "delims=" %%a in (test.txt) do (
   set /A i+=1
   set "line[!i!]=%%a"
   set "line=%%a"
   if "!line:morning=!" neq "%%a" set morning=present
   if "!line:evening=!" neq "%%a" set evening=present
   if "!line:~-4!" equ "****" (
      set "remove="
      if defined evening if not defined morning set remove=true
      if not defined remove for /L %%i in (1,1,!i!) do echo !line[%%i]!
      set i=0
      set "morning="
      set "evening="
   )
)

答案 3 :(得分:0)

还有一个。在这种情况下使用中间临时文件。

@echo off
    setlocal enableextensions disabledelayedexpansion

    :: configure and clean ouput/temporary files
    set "inputFile=inputFile.txt"
    set "outputFile=outputFile.txt"
    set "tempFile=%temp%\%~nx0.tmp"
    break>"%tempFile%"
    break>"%outputFile%"

    :: retrieve end of section lines
    for /f "tokens=1 delims=:" %%a in ('findstr /n /l /e /c:"****" "%inputFile%"') do set "_sect.%%a=1"

    :: extract each section and test for inclusion in output file
    for /f "tokens=1,* delims=:" %%a in ('findstr /n "^" "%inputFile%"') do (
        echo(%%b>>"%tempFile%"
        if defined _sect.%%a (
            find /i "morning" "%tempFile%" >nul && ( type "%tempFile%">>"%outputFile%" ) 
            break>"%tempFile%"
        )
    )

    :: clean and exit
    del /q "%tempFile%" 2>nul
    endlocal