如何从txt文件中减去字符串和非空值条目?

时间:2017-02-21 10:11:02

标签: regex parsing batch-file

我有一个脚本可以提取以下行:

THIS_IS_A_LINE:=

THIS_IS_A_LINE2:=

并将所有相同的类型输出到另一个.txt文件中:

THIS_IS_A_LINE

THIS_IS_A_LINE2

脚本如下:

set "file=%cd%/Config.mak"
set /a i=0
set "regexp=.*:=$"
setlocal enableDelayedExpansion
IF EXIST Source_List.txt del /F Source_List.txt
for /f "usebackq delims=" %%a in ("%file%") do (
    set /a i+=1
    call set Feature[!i!]=%%a
) 
cd .. && cd ..
rem call echo.!Feature[%i%]!
for /L %%N in (1,1,%i%) do (
    echo(!Feature[%%N]!|findstr /R /C:"%regexp%" >nul && (
        call echo FOUND
        call set /a j+=1
        call set Feature_Disabled[%j%]=!Feature[%%N]:~0,-2!
        call echo.!Feature_Disabled[%j%]!>>Source_List.txt
    ) || (
        call echo NOT FOUND 
    )  
) 
endlocal

我还有另一个脚本可以提取以下行:

THIS_IS_ANOTHER_LINE:= TRUE

THIS_IS_ANOTHER_LINE2:=真 ...

并将所有相同的类型输出到另一个.txt文件中:

THIS_IS_ANOTHER_LINE

THIS_IS_ANOTHER_LINE2 ...

脚本如下:

set "file=%cd%/Config.mak"
set /a i=0
set "regexp=.*:=true$"
setlocal enableDelayedExpansion
IF EXIST Source_List2.txt del /F Source_List2.txt
for /f "usebackq delims=" %%a in ("%file%") do (
    set /a i+=1
    call set Feature[!i!]=%%a
) 
cd .. && cd ..
rem call echo.!Feature[%i%]!
for /L %%N in (1,1,%i%) do (
    echo(!Feature[%%N]!|findstr /R /C:"%regexp%" >nul && (
        call echo FOUND
        call set /a j+=1
        call set Feature_Disabled[%j%]=!Feature[%%N]:~0,-6!
        call echo.!Feature_Disabled[%j%]!>>Source_List2.txt
    ) || (
        call echo NOT FOUND 
    )  
) 
endlocal

尽管如此,还有第三种包含数字的行(也是一些十六进制值),例如:

THIS_IS_AN_UNPROCESSED_LINE:= 0xA303

THIS_IS_AN_UNPROCESSED_LINE2:= 1943

THIS_IS_AN_UNPROCESSED_LINE3:= HELLO_DOOD_CAN_YOU_PARSE_ME

所以我需要这种方式将这些行提取到另一个.txt文件中,例如:

THIS_IS_AN_UNPROCESSED_LINE:= 0xA303

THIS_IS_AN_UNPROCESSED_LINE2:= 1943

THIS_IS_AN_UNPROCESSED_LINE3:= HELLO_DOOD_CAN_YOU_PARSE_ME

所以基本上提取不属于那种的行:

THIS_IS_AN_UNPROCESSED_LINE:=

THIS_IS_AN_UNPROCESSED_LINE:= TRUE

但保留行条目的两边。

我知道正则表达式必须有一些技巧,但我无法找到它。

1 个答案:

答案 0 :(得分:0)

你使代码变得比它需要的复杂得多。无需在文件中创建每行的数组。

如果在第一个:之前没有其他=:=,那么您可以使用FINDSTR打印出包含字符串的所有行,然后是{ {1}}。 :=可以捕获每个匹配行并将其解析为FOR /F之前和之后的部分,然后:=语句可以对三种不同类型的行进行分类。

我使用IF打开主代码块之外的所有三个输出文件以提高性能,然后我使用n>语法将每个输出定向到相应的已打开文件。我使用高编号文件句柄来避免Why doesn't my stderr redirection end after command finishes? And how do I fix it?中描述的问题。

&n>

以上内容会忽略@echo off setlocal set "file=Config.mak" set /a "empty=7, true=8, unprocessed=9" %empty%>empty.txt %true%>true.txt %unprocessed%>unprocessed.txt ( for /f "delims=:= tokens=1*" %%A in ('findstr /r "^[^:=][^:=]*:=" "%file%"') do ( if "%%B" equ "" ( >&%empty% (echo %%A) ) else if "%%B" equ "true" ( >&%true% (echo %%A) ) else ( >&%unprocessed% (echo %%A:=%%B) ) ) ) 之前包含:=的行,如果:=之后的第一个字符为:=,它将无法正常工作或:。我认为这应该不是问题。

使用PowerShell,VBScript或JScript编写一个非常有效的解决方案可以相对容易地消除限制。

您也可以使用JREPL.BAT - a powerful and efficient regular expression text processing command line utility。 JREPL.BAT是纯脚本(混合批处理/ JScrpt),可以在任何Windows机器上从XP开始本地运行,不需要第三方exe。 JREPL比任何纯批处理解决方案都快得多,特别是如果文件很大的话。

这是一个JREPL解决方案

=

如果您要做的就是将线条分类为三个不同的文件,而不必担心剥离空行和真行的@echo off setlocal set repl=^ $txt=false;^ if ($2=='') stdout.WriteLine($1);^ else if ($2=='true') stderr.WriteLine($1);^ else $txt=$0; call jrepl "^(.+):=(.*)$" "%repl%" /jmatchq^ /f Config.mak /o unprocessed.txt >empty.txt 2>true.txt :=true部分,那么就有一个非常简单的纯粹批量解决方案只使用FINDSTR。

:=