批处理Windows中的正则表达式 [英] Regex in Batch Windows

查看:60
本文介绍了批处理Windows中的正则表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在从事批处理作业(并且我对此也很陌生)以获取maven依赖项列表.一直在使用正则表达式来获取那些依赖项,但无济于事.我已经在此网站上测试了我的正则表达式,看来它正在工作.

从此 stackoverflow问题中检查了FOR循环中所需的转义字符,但仍然没有用因此,我不得不在这里寻求帮助.

有关我的代码段esp,请参见下文.正则表达式部分,外部循环很好.

 用于('findstr"+-\\-" dependency-list.txt')中的/f"tokens = *" %% ifor/f"tokens = *" %% j in('findstr/i/r"^^(.+ ^)\ [:\] ^(.+ ^)^(:jar:^)^(.+ ^)^(:compile ^)"%% i')做(回声%% j)) 

这是从我的外循环中获取的示例数据:

  [INFO] +-org.owasp.esapi:esapi:jar:2.0.1:compile[INFO] |+-commons-configuration:commons-configuration:jar:1.5:compile[INFO] ||+-commons-lang:commons-lang:jar:2.3:compile 

我只想使用正则表达式来获得这些部分:

  commons-configuration:commons-configuration:jar:1.5:compileorg.owasp.esapi:esapi:jar:2.0.1:compilecommons-lang:commons-lang:jar:2.3:compile 

这些是我尝试执行批处理脚本时遇到的错误.

  FINDSTR:无法打开org.owasp.esapi:esapi:jar:2.0.1:compile'+-'不被识别为内部或外部命令,可操作的程序或批处理文件.|在这个时候是出乎意料的. 

任何帮助将不胜感激.

注意:一旦我能够成功执行我的正则表达式,就可以删除外部循环.

解决方案

FINDSTR 的正则​​表达式功能非常有限,因为可以在打开命令提示符窗口并运行 findstr时读取它/?以获得输出帮助. FINDSTR 的正则​​表达式功能与 Perl兼容的正则表达式 Boost.Regex 或其他正则表达式Perl语法实现.

没有任何选项可用于仅通过正则表达式匹配的字符串通过 FINDSTR 获得输出.有几个选项可控制 FINDSTR 的输出,但没有一个选项仅用于输出找到的字符串.

因此,有必要删除文件 dependency-list.txt 中包含 +- \-的处理行上剩余的感兴趣数据的所有内容.代码>的另一种方法.Windows命令处理器仅提供两个用于字符串重新格式化任务的命令: FOR SET .

下面的批处理文件演示了这两个文件,其中考虑到访问同一命令块中定义/修改的环境变量的值需要延迟扩展.

  @echo关闭setlocal EnableExtensions DisableDelayedExpansioncls设置"DeleteExample =如果存在dependency-list.txt,请转到GetData(设置"DeleteExample = 1"回声第一行没有感兴趣的数据.回声[信息] +-org.owasp.esapi:esapi:jar:2.0.1:compile回声[INFO] ^ |+-commons-configuration:commons-configuration:jar:1.5:compile回声[INFO] ^ |^ |+-commons-lang:commons-lang:jar:2.3:compile回声; [INFO] ^ |\-commons-lang:commons-lang:jar:4.5:compile回声末尾的空格+-回声线,末尾无空格+-回声仅带有连字符的行-在行中的某处.回声[INFO] ^ |^ |+-!commons-configuration!:commons-configuration!:jar:5.2:compileecho最后一行没有相关数据.)> dependency-list.txt:获取数据回声优先解决方案回声===============回声/setlocal EnableDelayedExpansion为('%SystemRoot%\ System32 \ findstr.exe/R"+-\\-" dependency-list.txt 2 ^> nul')中的/F"tokens = *" %% I做(回声行读取:"%% I"设置线= %% I"设置"Line =!Line:*-=!"如果已定义Line echo Line work:!Line!"rem使用环境变量的更多命令rem感叹号用于在命令行执行时延迟扩展.)本地回声/回声秒解回声================回声/为/F"tokens = 1 * delims =-" %% I in('%SystemRoot%\ System32 \ findstr.exe/R"+-\\-"依赖项列表.txt')执行(如果不是"%% J" =="(回声行读取:"%% J"设置线= %% J"setlocal EnableDelayedExpansion通话设置线= %%线:〜1 %%"如果已定义,则线路呼叫回显线路工作:"%% Line %%"rem使用环境变量的更多命令参考行rem两侧带有两个百分号,并使用命令CALL.本地))回声/回声第三解回声===============回声/为/F"tokens = 1 * delims =-" %% I in('%SystemRoot%\ System32 \ findstr.exe/R"+-\\-" dependency-list.txt 2 ^> nul')执行(如果不是"%% J" =="(回声行读取:"%% J"对于/F"tokens = *"("%% J")中的%% L,如果不是"%% L" =="(回声行功:"%% L"rem更多使用循环变量L的命令.)))回声/回声第四解回声================回声/对于/F delims ^ = ^ eol ^ = %% I in('%SystemRoot%\ System32 \ findstr.exe/R"+-\\-" dependency-list.txt 2 ^> nul')执行(回声行读取:"%% I"设置线= %% I"setlocal EnableDelayedExpansion设置"Line =!Line:*-=!"如果已定义Line echo Line工作:!Line!"rem使用环境变量的更多命令rem感叹号用于在命令行执行时延迟扩展.本地)回声/回声第五解回声===============回声/为/F delims ^ = ^ eol ^ = %% I('%SystemRoot%\ System32 \ findstr.exe/L/C:+-/C:"\\-"依赖项列表.txt')执行(回声行读取:"%% I"设置线= %% I"致电:ProcessLine)转到EndDemo:生产线设置线=%线:*-=%"如果已定义Line echo Line work:%Line%"rem使用环境变量的更多命令在命令行执行之前,rem百分号表示扩展.转到:EOF:结束演示如果定义了DeleteExample deldependency-list.txt回声/本地暂停 

此批处理文件的输出为:

 第一个解决方案==============行读为:"[INFO] +-org.owasp.esapi:esapi:jar:2.0.1:compile"行工作:"org.owasp.esapi:esapi:jar:2.0.1:compile"行读为:"[INFO] | +-commons-configuration:commons-configuration:jar:1.5:compile"行工作:"commons-configuration:commons-configuration:jar:1.5:compile"行读为:"[INFO] | | +-commons-lang:commons-lang:jar:2.3:compile"行工作:"commons-lang:commons-lang:jar:2.3:compile"行读为:行尾的空格+-"行读为:行末没有空格+-"线工作:线末端无空格+-"行读为:"[INFO] | | +-:commons-configuration:jar:5.2:compile"行工作::commons-configuration:jar:5.2:compile"第二解决方案===============行读为:"org.owasp.esapi:esapi:jar:2.0.1:compile"行工作:"org.owasp.esapi:esapi:jar:2.0.1:compile"行读为:"commons-configuration:commons-configuration:jar:1.5:compile"行工作:"commons-configuration:commons-configuration:jar:1.5:compile"行读为:"commons-lang:commons-lang:jar:2.3:compile"行工作:"commons-lang:commons-lang:jar:2.3:compile"行读为:"行读为:!commons-configuration!:commons-configuration!:jar:5.2:compile"行工作:!commons-configuration!:commons-configuration!:jar:5.2:compile"第三种解决方案==============行读为:"org.owasp.esapi:esapi:jar:2.0.1:compile"行工作:"org.owasp.esapi:esapi:jar:2.0.1:compile"行读为:"commons-configuration:commons-configuration:jar:1.5:compile"行工作:"commons-configuration:commons-configuration:jar:1.5:compile"行读为:"commons-lang:commons-lang:jar:2.3:compile"行工作:"commons-lang:commons-lang:jar:2.3:compile"行读为:"行读为:!commons-configuration!:commons-configuration!:jar:5.2:compile"行工作:!commons-configuration!:commons-configuration!:jar:5.2:compile"第四解决方案===============行读为:"[INFO] +-org.owasp.esapi:esapi:jar:2.0.1:compile"行工作:"org.owasp.esapi:esapi:jar:2.0.1:compile"行读为:"[INFO] | +-commons-configuration:commons-configuration:jar:1.5:compile"行工作:"commons-configuration:commons-configuration:jar:1.5:compile"行读为:"[INFO] | | +-commons-lang:commons-lang:jar:2.3:compile"行工作:"commons-lang:commons-lang:jar:2.3:compile"行读为:; [INFO] | \-commons-lang:commons-lang:jar:4.5:compile"行工作:"commons-lang:commons-lang:jar:4.5:compile"读到的行:末尾的行尾空格+-"行读为:行末没有空格+-"线工作:线末端无空格+-"行读为:"[INFO] | | +-!commons-configuration!:commons-configuration!:jar:5.2:compile"行工作:!commons-configuration!:commons-configuration!:jar:5.2:compile"第五解决方案==============行读为:"[INFO] +-org.owasp.esapi:esapi:jar:2.0.1:compile"行工作:"org.owasp.esapi:esapi:jar:2.0.1:compile"行读为:"[INFO] | +-commons-configuration:commons-configuration:jar:1.5:compile"行工作:"commons-configuration:commons-configuration:jar:1.5:compile"行读为:"[INFO] | | +-commons-lang:commons-lang:jar:2.3:compile"行工作:"commons-lang:commons-lang:jar:2.3:compile"行读为:; [INFO] | \-commons-lang:commons-lang:jar:4.5:compile"行工作:"commons-lang:commons-lang:jar:4.5:compile"行读为:行尾的空格+-"行读为:行末没有空格+-"行工作:行末没有空格+-"行读为:"[INFO] | | +-!commons-configuration!:commons-configuration!:jar:5.2:compile"行工作:!commons-configuration!:commons-configuration!:jar:5.2:compile" 

前四个解决方案在以 cmd.exe/C 开头的单独命令过程中在命令行后台运行:

  C:\ Windows \ System32 \ findstr.exe/R"+-\\-"依赖项列表.txt 

此命令行导致在当前目录中搜索文件 dependency-list.txt ,该目录可能与批处理文件的目录不同,使用区分大小写的正则表达式查找包含的行+- \-.

第五种解决方案在单独的命令行中运行命令行:

  C:\ Windows \ System32 \ findstr.exe/L/C:+-/C:"\\-"dependency-list.txt 

此命令行查找相同的行,但是使用区分大小写的文字搜索来查找包含 +- \-的行.

在找不到任何包含 +-的行时,

FINDSTR 不会输出到 STDOUT ,也不会输出到 STDERR \-.

FOR 将输出捕获到单独命令过程的 STDOUT 并逐行处理输出.

空行被 FOR 忽略,因为默认情况下,由于 eol =; 是行尾字符选项的默认设置,因此也以分号开头的行. FOR 默认情况下使用常规空格和水平制表符作为字符串定界符将行拆分为子字符串(令牌),并仅将第一个空格/制表符分隔的字符串分配给指定的循环变量.

第一个解决方案

第一个解决方案通过使用选项 tokens = * 修改 FOR 的行处理行为,这会导致删除行中的所有前导空格/制表符,以及是否还有剩余内容将其余行(包括空格/制表符)分配给指定的循环变量 I .输出中以 Line read:开头的行显示了通过 FOR 处理后分配给循环变量 I 的字符串.

此字符串分配给环境变量 Line .然后,使用由命令 SET 完成的字符串替换,并使用延迟的环境变量扩展(根据引用环境值的要求),从行中删除直到首次出现的由连字符和空格组成的字符串为止的所有内容在命令块中以()开头并以匹配的)结尾的变量.

如果在字符串替换后还剩下一些东西,导致仍然定义了环境变量 Line ,则该行的其余部分将通过 Line work:输出,以查看字符串替换完成了什么.

此解决方案速度很快,但缺点是 FOR 会忽略以分号开头的行,并且永久启用的延迟环境变量扩展会导致包含不正确处理的一个或多个感叹号的行.但是,这是文件 dependency-list.txt 上的最佳解决方案,它永远不会包含以; 开头并包含一个或多个的感兴趣的行.

第二个解决方案

第二种解决方案使用命令 FOR 将不以分号开头的每个非空行拆分为两个子字符串.直到一个或多个-首次出现的第一个子字符串分配给指定的循环变量 I ,其余行分配给下一个循环变量 J 根据 ASCII 表.

因此,对于示例行 J 包含感兴趣的数据,并且在开头不是空字符串的情况下使用前导空格.通过再次使用命令 SET 来分配给环境变量 Line ,最后仅删除从第二个字符开始的字符串,该第二个字符的字符索引为1,直到字符串的结尾.>

但是,不是使用延迟扩展,而是使用另一种技术,即通过引用之前在命令块中设置的环境变量值(两侧带有两个百分号)并使用命令 CALL 来强制 Windows命令处理器在执行命令 SET ECHO 之前解析这两行第二次.因此,在执行 FOR 之前解析整个命令块时,使用 CALL 的两行代码变为:

 呼叫设置"Line =%Line:〜1%"如果已定义线路呼叫回显线路工作:%Line% 

由于命令 CALL ,第二次在循环的每次迭代中解析这两行,从而导致替换%Line:〜1%%Line%分别在执行 set echo 之前分别完全不带第一个字符.

此解决方案正确处理了包含感叹号的目标行,因为避免了使用延迟扩展.

第三种解决方案

第三种解决方案类似于第二种解决方案.它使用第二个 FOR 从外部 FOR 分配给循环变量 J 的字符串中删除所有前导空格/制表符,并将其余字符串分配给循环变量 L ,甚至可以是一个空字符串.

由于速度更快,该解决方案绝对比第二种解决方案好.

第四种解决方案

编写这四个解决方案是始终将捕获的输出中的整个非空行分配给循环变量 I ,而与第一个字符是哪个字符无关.通过定义一个空的定界符列表可以禁用行拆分行为,并且可以使用无行结束符的定义来禁用忽略以特定字符开头的行.

删除字符串,直到第一个连字符和空格第一次出现,就像在第一个解决方案中一样.区别在于,在将行分配给环境变量 Line 时,禁用了延迟扩展,仅在下一次临时启用该行以处理行字符串.

此解决方案的缺点是,循环内的命令 setlocal EnableDelayedExpansion endlocal 不仅能启用和禁用延迟扩展,还具有更多功能.有关命令 SETLOCAL ENDLOCAL 的详细信息,请参见此答案.因此,此解决方案绝对不是所提供解决方案中最快的解决方案.

第五种解决方案

第五种解决方案与第四种解决方案相似,不同之处在于它展示了一种通用技术,该技术可通过使用在 FOR 循环中使用的子例程来避免对延迟处理扩展字符串中的字符串值使用延迟扩展strong> FOR 循环.

该解决方案也非常慢,但是具有一个很大的优势,即在批处理文件中位于顶部的 @echo ON 上运行该批处理文件时,可以更轻松地调试该批处理文件.

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

  • 呼叫/?
  • cls/?
  • del/?
  • echo/?
  • endlocal/?
  • findstr/?
  • 用于/?
  • 转到/?
  • 如果/?
  • 暂停/?
  • rem/?
  • 设置/?
  • setlocal/?

I am currently working on a batch job(and I am new to this as well) to get a list of maven dependencies . Been working to fetch those dependencies using regex but to no avail. I have tested my regex on this site and it seems it's working.

Checked the needed escape characters inside a FOR loop from this stackoverflow question but again, to not avail thus I have resorted to ask help in here.

See below for my code snippet esp. the regex part, the outer loop is fine.

for /f "tokens=*" %%i in ('findstr "+- \\-"  dependency-list.txt') do (
    for /f "tokens=*" %%j in ('findstr /i /r "^^(.+^)\[:\]^(.+^)^(:jar:^)^(.+^)^(:compile^)" %%i') do (
        echo %%j
    )
)

And this is the sample data fetched from my outer loop:

[INFO] +- org.owasp.esapi:esapi:jar:2.0.1:compile
[INFO] |  +- commons-configuration:commons-configuration:jar:1.5:compile
[INFO] |  |  +- commons-lang:commons-lang:jar:2.3:compile

I wanted to get these part only using regex:

commons-configuration:commons-configuration:jar:1.5:compile
org.owasp.esapi:esapi:jar:2.0.1:compile
commons-lang:commons-lang:jar:2.3:compile

These are the errors I'm getting when trying to execute my batch script.

FINDSTR: Cannot open org.owasp.esapi:esapi:jar:2.0.1:compile
'+-' is not recognized as an internal or external command,
operable program or batch file.
| was unexpected at this time.

Any help would be greatly appreciated.

NOTE: Once I am able to execute my regex successfully, the outer loop can be removed.

解决方案

The regular expression capabilities of FINDSTR are very limited as it can be read on opening a command prompt window and running findstr /? to get output its help. The regular expression capabilities of FINDSTR are far away from Perl compatible regular expressions or Boost.Regex or other regular expression implementations in Perl syntax.

There is no option which can be used to get output by FINDSTR only the string matched by a regular expression. There are several options which controls the output of FINDSTR, but none for getting output just the found string.

So it is necessary to remove everything left to data of interest on processing lines containing +- or \- in file dependency-list.txt with a different method. Windows command processor offers just two commands for string reformatting tasks: FOR and SET.

The batch file below demonstrates both of them taking into account that delayed expansion is needed on accessing value of an environment variable defined/modified in same command block.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
set "DeleteExample="
if exist dependency-list.txt goto GetData
(
    set "DeleteExample=1"
    echo First line with no data of interest.
    echo [INFO] +- org.owasp.esapi:esapi:jar:2.0.1:compile
    echo [INFO] ^|  +- commons-configuration:commons-configuration:jar:1.5:compile
    echo [INFO] ^|  ^|  +- commons-lang:commons-lang:jar:2.3:compile
    echo ;[INFO]^|  \- commons-lang:commons-lang:jar:4.5:compile
    echo Line trailing space at end +- 
    echo Line with no space at end  +-
    echo Line with just a hyphen character - somewhere on line.
    echo [INFO] ^|  ^|  +- !commons-configuration!:commons-configuration!:jar:5.2:compile
    echo Last line with no data of interest.
)>dependency-list.txt

:GetData
echo First solution
echo ==============
echo/
setlocal EnableDelayedExpansion
for /F "tokens=*" %%I in ('%SystemRoot%\System32\findstr.exe /R "+- \\-" dependency-list.txt 2^>nul') do (
    echo Line read: "%%I"
    set "Line=%%I"
    set "Line=!Line:*- =!"
    if defined Line echo Line work: "!Line!"
    rem More commands working with environment variable Line referenced with
    rem exclamation marks for delayed expansion on execution of the command line.
)
endlocal

echo/
echo Second solution
echo ===============
echo/
for /F "tokens=1* delims=-" %%I in ('%SystemRoot%\System32\findstr.exe /R "+- \\-" dependency-list.txt') do (
    if not "%%J" == "" (
        echo Line read: "%%J"
        set "Line=%%J"
        setlocal EnableDelayedExpansion
        call set "Line=%%Line:~1%%"
        if defined Line call echo Line work: "%%Line%%"
        rem More commands working with environment variable Line referenced
        rem with two percent signs on both side and with using command CALL.
        endlocal
    )
)

echo/
echo Third solution
echo ==============
echo/
for /F "tokens=1* delims=-" %%I in ('%SystemRoot%\System32\findstr.exe /R "+- \\-" dependency-list.txt 2^>nul') do (
    if not "%%J" == "" (
        echo Line read: "%%J"
        for /F "tokens=*" %%L in ("%%J") do if not "%%L" == "" (
            echo Line work: "%%L"
            rem More commands working with loop variable L.
        )
    )
)

echo/
echo Fourth solution
echo ===============
echo/
for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /R "+- \\-" dependency-list.txt 2^>nul') do (
    echo Line read: "%%I"
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    set "Line=!Line:*- =!"
    if defined Line echo Line work: "!Line!"
    rem More commands working with environment variable Line referenced with
    rem exclamation marks for delayed expansion on execution of the command line.
    endlocal
)

echo/
echo Fifth solution
echo ==============
echo/
for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /L /C:+- /C:"\\-" dependency-list.txt') do (
    echo Line read: "%%I"
    set "Line=%%I"
    call :ProcessLine
)
goto EndDemo

:ProcessLine
set "Line=%Line:*- =%"
if defined Line echo Line work: "%Line%"
rem More commands working with environment variable Line referenced with
rem percent signs for expansion before execution of the command line.
goto :EOF

:EndDemo
if defined DeleteExample del dependency-list.txt
echo/
endlocal
pause

The output of this batch file is:

First solution
==============

Line read: "[INFO] +- org.owasp.esapi:esapi:jar:2.0.1:compile"
Line work: "org.owasp.esapi:esapi:jar:2.0.1:compile"
Line read: "[INFO] |  +- commons-configuration:commons-configuration:jar:1.5:compile"
Line work: "commons-configuration:commons-configuration:jar:1.5:compile"
Line read: "[INFO] |  |  +- commons-lang:commons-lang:jar:2.3:compile"
Line work: "commons-lang:commons-lang:jar:2.3:compile"
Line read: "Line trailing space at end +- "
Line read: "Line with no space at end  +-"
Line work: "Line with no space at end  +-"
Line read: "[INFO] |  |  +- :commons-configuration:jar:5.2:compile"
Line work: ":commons-configuration:jar:5.2:compile"

Second solution
===============

Line read: " org.owasp.esapi:esapi:jar:2.0.1:compile"
Line work: "org.owasp.esapi:esapi:jar:2.0.1:compile"
Line read: " commons-configuration:commons-configuration:jar:1.5:compile"
Line work: "commons-configuration:commons-configuration:jar:1.5:compile"
Line read: " commons-lang:commons-lang:jar:2.3:compile"
Line work: "commons-lang:commons-lang:jar:2.3:compile"
Line read: " "
Line read: " !commons-configuration!:commons-configuration!:jar:5.2:compile"
Line work: "!commons-configuration!:commons-configuration!:jar:5.2:compile"

Third solution
==============

Line read: " org.owasp.esapi:esapi:jar:2.0.1:compile"
Line work: "org.owasp.esapi:esapi:jar:2.0.1:compile"
Line read: " commons-configuration:commons-configuration:jar:1.5:compile"
Line work: "commons-configuration:commons-configuration:jar:1.5:compile"
Line read: " commons-lang:commons-lang:jar:2.3:compile"
Line work: "commons-lang:commons-lang:jar:2.3:compile"
Line read: " "
Line read: " !commons-configuration!:commons-configuration!:jar:5.2:compile"
Line work: "!commons-configuration!:commons-configuration!:jar:5.2:compile"

Fourth solution
===============

Line read: "[INFO] +- org.owasp.esapi:esapi:jar:2.0.1:compile"
Line work: "org.owasp.esapi:esapi:jar:2.0.1:compile"
Line read: "[INFO] |  +- commons-configuration:commons-configuration:jar:1.5:compile"
Line work: "commons-configuration:commons-configuration:jar:1.5:compile"
Line read: "[INFO] |  |  +- commons-lang:commons-lang:jar:2.3:compile"
Line work: "commons-lang:commons-lang:jar:2.3:compile"
Line read: ";[INFO]|  \- commons-lang:commons-lang:jar:4.5:compile"
Line work: "commons-lang:commons-lang:jar:4.5:compile"
Line read: "Line trailing space at end +- "
Line read: "Line with no space at end  +-"
Line work: "Line with no space at end  +-"
Line read: "[INFO] |  |  +- !commons-configuration!:commons-configuration!:jar:5.2:compile"
Line work: "!commons-configuration!:commons-configuration!:jar:5.2:compile"

Fifth solution
==============

Line read: "[INFO] +- org.owasp.esapi:esapi:jar:2.0.1:compile"
Line work: "org.owasp.esapi:esapi:jar:2.0.1:compile"
Line read: "[INFO] |  +- commons-configuration:commons-configuration:jar:1.5:compile"
Line work: "commons-configuration:commons-configuration:jar:1.5:compile"
Line read: "[INFO] |  |  +- commons-lang:commons-lang:jar:2.3:compile"
Line work: "commons-lang:commons-lang:jar:2.3:compile"
Line read: ";[INFO]|  \- commons-lang:commons-lang:jar:4.5:compile"
Line work: "commons-lang:commons-lang:jar:4.5:compile"
Line read: "Line trailing space at end +- "
Line read: "Line with no space at end  +-"
Line work: "Line with no space at end  +-"
Line read: "[INFO] |  |  +- !commons-configuration!:commons-configuration!:jar:5.2:compile"
Line work: "!commons-configuration!:commons-configuration!:jar:5.2:compile"

The first four solutions run in a separate command process started with cmd.exe /C in background the command line:

C:\Windows\System32\findstr.exe /R "+- \\-" dependency-list.txt

This command line results in searching in file dependency-list.txt in current directory which can be different to directory of the batch file with a case-sensitive regular expression for lines containing either +- or \-.

The fifth solution runs in separate command process the command line:

C:\Windows\System32\findstr.exe /L /C:+- /C:"\\-" dependency-list.txt

This command line finds the same lines, but with using a case-sensitive literal search for finding lines containing either +- or \-.

FINDSTR outputs nothing to STDOUT and also nothing to STDERR on not finding any line containing either +- or \-.

FOR captures the output to STDOUT of separate command process and processes the output line by line.

Empty lines are ignored by FOR as by default also lines starting with a semicolon because of eol=; is the default for end of line character option. FOR splits up by default the line into substrings (tokens) using normal space and horizontal tab character as string delimiters and assigns just first space/tab delimited string to the specified loop variable.

First solution

The first solution modifies line processing behavior of FOR by using option tokens=* which results in removing all leading spaces/tabs from a line and if there is something left assigned the rest of the line with including spaces/tabs to the specified loop variable I. The lines in output starting with Line read: shows the string assigned to loop variable I after line processing by FOR.

This string is assigned to environment variable Line. Then everything up to first occurrence of a string consisting of a hyphen and a space is removed from the line using a string substitution done by command SET with using delayed environment variables expansion as required on referencing value of an environment variable defined/modified inside a command block starting with ( and ending with matching ).

If there is still something left after the string substitution resulting in environment variable Line being still defined, this remaining part of the line is output with Line work: to see what was done by the string substitution.

This solution is fast, but have the disadvantages that lines starting with a semicolon are ignored by FOR and permanently enabled delayed environment variable expansion results in getting a line containing one or more exclamation marks not processed correct. However, this is the best solution on file dependency-list.txt contains never lines of interest starting with ; and containing one or more !.

Second solution

The second solution uses command FOR to split up each non-empty line not starting with a semicolon into two substrings. The first substring up to first occurrence of one or more - is assigned to specified loop variable I and the rest of the line to next loop variable J according to ASCII table.

So for the example lines J contains the data of interest with a leading space on not being an empty string. The leading space is removed on using again command SET to get assigned to environment variable Line finally only the string from second character with character index 1 up to end of string.

But instead of using delayed expansion a different technique is used by referencing the environment variable value just set before in the command block with two percent signs on both side and use command CALL to force Windows command processor to parse the two lines before execution of the commands SET or ECHO a second time. So on parsing the entire command block before executing FOR the two lines with CALL became:

call set "Line=%Line:~1%"
if defined Line call echo Line work: %Line%

Those two lines are parsed on each iteration of the loop a second time because of command CALL resulting in replacing %Line:~1% and %Line% by current string without first character respectively completely before executing set and echo.

The lines of interest containing an exclamation mark are processed correct by this solution because of avoiding usage of delayed expansion.

Third solution

The third solution is similar to second solution. It uses a second FOR to remove all leading spaces/tabs from string assigned to loop variable J by the outer FOR and assigns the remaining string to loop variable L which can be even an empty string.

This solution is definitely better than the second solution because of being faster.

Fourth solution

The four solution is written to assign to loop variable I always the entire non-empty line from captured output independent on which character is the first character. Line splitting behavior is disabled with definition of an empty list of delimiters and ignoring lines starting with a specific character is disabled with definition of no end of line character.

Removal of string left to first occurrence of hyphen and space is done like in first solution. The difference is that delayed expansion is disabled on assigning the line to environment variable Line and just enabled next temporarily for processing the line string.

The disadvantage of this solution is that the commands setlocal EnableDelayedExpansion and endlocal inside the loop do much more than just enabling and disabling delayed expansion. See this answer for details about the commands SETLOCAL and ENDLOCAL. So this solution is definitely not the fastest one in set of provided solutions.

Fifth solution

The fifth solution is similar to fourth solution with the difference to show the common technique for avoiding the usage of delayed expansion on processing string values inside a FOR loop by using a subroutine called from within the FOR loop.

This solution is also very slow, but has the big advantage for easier debugging the batch file on running it with @echo ON at top from within a batch file.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • cls /?
  • del /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

这篇关于批处理Windows中的正则表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆