批处理文件:使用特殊字符提取两个字符串之间的子字符串

时间:2019-12-05 15:03:34

标签: windows batch-file cmd

当它包含特殊字符时,我对Windows批处理字符串和子字符串的批处理方式感到困惑。

我从脚本中获得了此变量:

echo "%longString"

返回我的

"<p style="text-align: center;"><a class="more" href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">Download</a></p><p style="text-align: center;"><a href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">64-Bit Graphical Installer (462 MB)</a></p><p style="text-align: center;"><a href="https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86.exe">32-Bit Graphical Installer (410 MB)</a></p></div>"

我唯一感兴趣的部分是在a href="">64-Bit Graphical之间。

然后,使用类似的question(但我不包含特殊字符的困难),我尝试了所提出解决方案的许多组合,但是每次遇到特殊字符时,我的案子都得到意外的结果。

我认为不可行的例子可能是

@ECHO OFF

:: define the longstring
Call Set "longString=<p style="text-align: center;"><a class="more" href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">Download</a></p><p style="text-align: center;"><a href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">64-Bit Graphical Installer (462 MB)</a></p><p style="text-align: center;"><a href="https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86.exe">32-Bit Graphical Installer (410 MB)</a></p></div>"

:: Define subtrings token
Set "subsA=a href=""
Set "subsB=>64-Bit Graphical"

:: Remove part before subsA
Call set "Result=%%longString:*%subsA%=%%"
:: extract part to remove behind subsB
Call set "Remove=%%Result:*%subsB%=%%"
:: remove part behind subsB
Call set "Result=%%Result:%Remove%=%%"

Echo "%Result%"

目前,我最好的结果是使用Set "subsA=href"Set "subsB=64-Bit"(因此更简单,因为其中没有特殊字符),这使我可以进行Result的第一个设置和Remove,但是因为这些新变量包含许多特殊字符,所以Result的最后设置给我带来了麻烦。

我也尝试使用For /Ffindstr,但结果甚至更糟。

所以我很想找到任何解决方案或解释。

2 个答案:

答案 0 :(得分:2)

好吧,由于您尝试提取通常不应该包含引号的URL,因此可以执行以下操作:

  • 分割所有内容,包括setTextContent(String)(为了从sub-string substitution开始使用,我故意从此搜索字符串中删除了a href=",因为="分隔了搜索并替换字符串);
  • 将其余的字符串拆分为=个字符,然后提取第二部分(第一部分为");

这是一个可能的解决方案:

=

答案 1 :(得分:1)

不要将call与特殊字符一起使用,只会变得更糟(在这种情况下,即使CALL也可以使用,但这仅是运气)。

Set "longString=<p style="text-align: center;"><a class="more" href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">Download</a></p><p style="text-align: center;"><a href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">64-Bit Graphical Installer (462 MB)</a></p><p style="text-align: center;"><a href="https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86.exe">32-Bit Graphical Installer (410 MB)</a></p></div>"

最好使用延迟扩展,因为延迟扩展的结果对于所有字符都是安全的。

即使第一部分失败

:: Define subtrings token
Set "subsA=a href=""
:: Remove part before subsA
set "Result=!longString:*%subsA%=!"

这里的问题是subA a href="中的等号,第一个等号用作search=replace表达式中的定界符。
最好将搜索字符串更改为仅Set "subsA=a href"

现在您已或多或少地拥有正确的字符串,只需set result=!result:~2!就可以删除前两个字符

您删除字符串尾部的想法很好,但是不能批量使用,REMOVE字符串中等号再次出现问题。

但是您可以简单地计算删除字符串的长度,该长度可用于按位置将其从结果中删除。
但是remove_len中的长度太短,因为缺少了subsB本身的长度。

set "remove=!result:*%subsB%=!"
call :strlen remove_len remove
set "result=!result:~0,-%remove_len%!"

echo !result!

要感到惊讶,可以使用类似SO:How do you get the string length in a batch file?

的函数

结果代码如下

@echo off
setlocal
Set "longString=<p style="text-align: center;"><a class="more" href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">Download</a></p><p style="text-align: center;"><a href=" https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86_64.exe">64-Bit Graphical Installer (462 MB)</a></p><p style="text-align: center;"><a href="https://repo.anaconda.com/archive/Anaconda3-2019.10-Windows-x86.exe">32-Bit Graphical Installer (410 MB)</a></p></div>"

setlocal EnableDelayedExpansion

:: Define subtrings token
Set "subsA=a href"
Set "subsB=>64-Bit Graphical"

:: Remove part before subsA
set "Result=!longString:*%subsA%=!"
set "Result=!result:~2!"
set result
set "remove=!result:*%subsB%=!"
set remove
call :strlen remove_len remove
call :strlen subsB_len subsB
set /a remove_len+=subsB_len+1
set "result=!result:~0,-%remove_len%!"

echo !result!
   exit /b


:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    (set^ tmp=!%~2!)
    if defined tmp (
        set "len=1"
        for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
            if "!tmp:~%%P,1!" NEQ "" ( 
                set /a "len+=%%P"
                set "tmp=!tmp:~%%P!"
            )
        )
    ) ELSE (
        set len=0
    )
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)