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



当它包含特殊字符时,我对处理字符串和子字符串的 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之间。

然后,使用这个类似的问题(但我不包含特殊字符的难度(,我尝试了许多建议的解决方案组合,但由于特殊字符,每次我的情况都得到了意想不到的结果。

我认为一个不工作的例子可能是

@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"(所以它更简单,因为其中没有特殊字符(,这允许我完成ResultRemove的第一个设置,但随后因为这些新变量包含许多特殊字符,Result的最后一个设置给了我废话。

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

所以我渴望找到任何解决方案或/和解释。

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

  • 拆分所有内容,包括a href="(我故意从此搜索字符串中删除="以便能够使用子字符串替换,因为=分隔搜索和替换字符串(;
  • 将剩余的字符串拆分为"个字符并提取第二部分(第一部分为=(;

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

@echo off
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>"
rem // Use delayed expansion to avoid trouble with `"` and other special characters:
setlocal EnableDelayedExpansion
rem // Split off everything up to and including `a href`, then extract the second token in between `""`:
for /F tokens^=1^,2^ delims^=^"^ eol^=^" %%I in ("!longString:*a href=!") do (
endlocal
rem // Check for leading `=`-sign (could be skipped if not needed):
if not "%%I"=="=" >&2 echo ERROR!& goto :EOF
rem // Remove leading whitespaces:
for /F "tokens=* eol= " %%K in ("%%J") do set "partString=%%K"
)
rem // Return extracted URL:
echo/%partString%

不要将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%=!"

问题是这里的等号在子 Aa 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!

要获取 strlen,您可以使用类似 SO:如何获取批处理文件中的字符串长度?

生成的代码如下所示

@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
)

最新更新