命令行:获取两个不同分隔符之间的子字符串

命令行:获取两个不同分隔符之间的子字符串

我如何能够获取两个不同分隔符之间的子字符串,该子字符串也位于给定字符串内的可变位置。

例如:

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 字符串的子字符串,因为它不在其内容中。

相关内容