我如何能够获取两个不同分隔符之间的子字符串,该子字符串也位于给定字符串内的可变位置。
例如:
String1 = "my first example {{my first substring}}"
String2 = "my great second example which has much more words included before {{my second substring}} and after the substring"
Substring1 = "my first substring"
Substring2 = "my second substring"
如您所见,子字符串之前的分隔符是“{{”,之后的分隔符是“}}”。
我发现有关子串操作的所有信息都是严格的位置设置,但这没有帮助。
提前致谢!
答案1
我假设您只需要每个字符串中的一个子字符串。这是一个强大的解决方案,它可以处理任何值,但不能处理!
的值除外,并且如果值中包含 ,也会^
被删除。!
@echo off
setlocal enableDelayedExpansion
for %%S in (
"my {{first substring}} example"
"my {ignore {{second substring}} example"
"my {{third {sub}string}} example"
"poison character {{&|<>^^ "^&^|^<^>^^^^"}} example"
"empty {{}} example"
"my {first error}} example"
"my {{second error} example"
"my third error example{{"
""
"Limitation: {{eclamation is stripped^^^!}}"
"Limitation: {{caret ^^^^ is stripped if exclamation present^^^!}}"
) do (
set "string=%%~S"
echo(!string!
call :get{{sub}} string sub && echo(!sub! || echo ERROR: substring not found
echo(
)
exit /b
:get{{sub}} inStrVar subStrVar
setlocal enableDelayedExpansion
set "str=!%~1!"
if not defined str exit /b 1
set "sub1=!str:*{{=!"
if not defined sub1 exit /b 1
if "!sub1!"=="!str!" exit /b 1
set "sub="
for %%N in (^"^
^") do for /f "delims=" %%A in ("x!sub1:}}=%%~N!") do if not defined sub set "sub=%%A"
set "sub=!sub:~1!"
if "!sub!"=="!sub1!" exit /b 1
for /f delims^=^ eol^= %%A in (""!sub!"") do endlocal & set "%~2=%%~A" & exit /b 0
- 输出 -
my {{first substring}} example
first substring
my {ignore {{second substring}} example
second substring
my {{third {sub}string}} example
third {sub}string
poison character {{&|<>^ "&|<>^"}} example
&|<>^ "&|<>^"
empty {{}} example
my {first error}} example
ERROR: substring not found
my {{second error} example
ERROR: substring not found
my third error example{{
ERROR: substring not found
ERROR: substring not found
Limitation: {{eclamation is stripped!}}
eclamation is stripped
Limitation: {{caret ^ is stripped if exclamation present!}}
caret is stripped if exclamation present
获取子字符串主要有两个技巧。
!str:*{{!
删除直到第一次出现的所有内容{{
。for %%N in ...
在 中创建一个带引号的换行符,%%N
以便 用!sub:{{=%%~N!
换行符替换所有}}
。然后内部for /f
分别迭代每个字符串,do
循环仅保留第一个结果。x
仅在子字符串为空时才添加 。
答案2
@echo off
cls
setlocal ENABLEDELAYEDEXPANSION
set String1=my first example {{my first substring}}
set String2=my great second example which has much more words included before {{my second substring}} and after the substring
call :extract %String1%
echo %Substring%
call :extract %String2%
echo %Substring%
endlocal
goto :EOF
:extract
for /f "delims={ tokens=2" %%x in ("%*") do (
set Substring=%%x
)
for /f "delims=}" %%x in ("%Substring%") do (
set Substring=%%x
)
exit /b
我不认为这会给出正确的结果。例如 --- {{abc {123} xyz}} --- 得出 abc 但我认为正确的结果是 abc {123} xyz。– dbenham
没错。为了解决这个问题,我们必须有一些源字符串中不存在的可打印字符(至少在最终确定分隔符之前)。
例如,如果这样的字符是@
代码可能是
@echo off
cls
setlocal ENABLEDELAYEDEXPANSION
set String1=my first example {{my first substring}}
set String2=my great second example which has much more words included before {{my second substring}} and after the substring
set String3=--- {{abc {123} xyz}} ---
call :extract %String1%
echo %Substring%
call :extract %String2%
echo %Substring%
call :extract %String3%
echo %Substring%
endlocal
goto :EOF
:extract
set tempstr=%*
set tempstr=%tempstr:{{=@%
set tempstr=%tempstr:}}=@%
for /f "delims=@ tokens=2" %%x in ("%tempstr%") do (
set Substring=%%x
)
exit /b
答案3
我想我找到了一个解决方案:
set string="my great second example which has much more words included before {{my second substring}} and after the substring"
echo string: %string%
set "tmp=%string:{=" & set "tmp=%"
echo tmp: %tmp%
for /f "delims=}" %%a in ("%tmp%") do set substr=%%a
echo substr: %substr%
结果:
string: "my great second example which has much more words included before {{my second substring}} and after the substring"
tmp: "my great second example which has much more words included before "
substr: my second substring
它可以工作,但我不太明白它如何能够确定 tmp 字符串的子字符串,因为它不在其内容中。