从具有分隔符随机数的字符串中获取变量 [cmd]
Get variable from string with random numbers of delimiter [cmd]
我有一个包含许多分隔符“_”的文件夹:text4_text5_text6_text7_2000-01-02
我需要从中创建 2 个变量。第一个是从文件夹名称到最后一个分隔符的所有内容。第二个在最后一个分隔符之后:
- %name% = text4_text5_text6_text7
- %日期% = 2000-01-02
日期我有这个代码:
SET DIR = text4_text5_text6_text7_2000-01-02
FOR %%a in (%DIR:_= %) do set DATE=%%a
但我不知道在 %DATE% 之前将 %NAME% 其他所有内容都考虑在内。
我将不胜感激。
您可以将所有值放入字符串数组中。数组的最后一个值必须是 %date%.
@ECHO OFF
SET name=text4_text5_text6_text7_2000-01-02
SET /A id=0
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%a in (%name:_= %) DO (
SET /A id+=1
SET arr[!id!]=%%a
)
REM PRINT ALL VALUES WHERE %id% IS THE LAST ARRAY NUMBER
FOR /L %%i in (1,1,%id%) DO @ECHO !arr[%%i]!
REM PRINT ONLY DATE
@ECHO !arr[%id%]!
ENDLOCAL
如果格式如您所述,最后一个 _
始终包含以下日期:
@echo off
setlocal enabledelayedexpansion
set "name=text4_text5_text6_text7_2000-01-02"
for %%i in (%name:_= %) do set "mydate=%%i"
set "restofline=!name:%mydate%=!"
echo %restofline:~0,-1% %mydate%
此处 %mydate%
是包含日期的变量,%restofline%
包含其余部分。
这里有一个应用有时 so-called 代码注入技术的方法:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define (non-empty) input string here:
set "name=text4_text5_text6_text7_2000-01-02"
rem // Clear variables:
set "rest=" & set "last="
rem // Split off the last `_`-separated item using the code injection technique:
set "rest=%name:_=" & (if defined last set "rest=!rest!_!last!") & set "last=%"
rem // Return result:
set name
set rest
set last
endlocal
pause
相关的控制台输出如下:
name=text4_text5_text6_text7_2000-01-02
rest=text4_text5_text6_text7
last=2000-01-02
要了解它是如何工作的,请将 @echo off
更改为 @echo on
并检查控制台输出。此方法基于 sub-string substitution, and it requires delayed variable expansion.
请注意,如果字符串包含 !
、^
和 "
。
,此方法将失败
注意,多个连续的分隔符合并为一个,因此像 abc__def__01
这样的字符串将被拆分为 abc_def
和 01
。为避免这种情况并保留分隔符,请将核心代码更改为:
rem // Clear variables:
set "rest=" & set "last=" & set "flag="
rem // Split off the last `_`-separated item using the code injection technique:
set "rest=%name:_=" & (if defined flag (set "rest=!rest!_!last!") else set "flag=#") & set "last=%"
有关此方法的更多信息,请参阅 split string into substrings based on delimiter [DosTips]。
这是一种基于您的代码并使用标准 for
循环的方法:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define (non-empty) input string here:
set "name=text4_text5_text6_text7_2000-01-02"
rem // Reset variables:
set "rest=_" & set "last="
rem // Split off the last `_`-separated item using a `for` loop:
for %%a in ("%name:_= %") do (
rem // This assignment is always one iteration behind:
if defined last set "rest=!rest!_!last!"
rem // This value is available for the next iteration:
set "last=%%a"
)
rem // Strip off leading `__`:
set "rest=%rest:~2%"
rem // Return result:
set name
set rest
set last
endlocal
pause
请注意,对于包含 wildcards 的字符串,如 ?
、*
和 <
、>
,此方法将失败;此外,!
、^
和 "
不得出现在字符串中。
为了至少避免字符串中的 !
、^
和 "
出现问题,请改用这个更健壮但更复杂的代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define input string here:
set "name=text4_text5_text6_text7_2000-01-02"
rem // Reset variables:
set "rest=_" & set "last=" & set "flag="
rem // Double quotes to avoid issues with such:
setlocal EnableDelayedExpansion
set "name=!name:"=""!^" & rem ^"
rem // Split off the last `_`-separated item using a `for` loop:
if defined name for %%a in ("!name:_=" "!") do (
rem // Use `for /F` to transfer string beyond `endlocal` barrier:
for /F "delims=" %%b in ("!rest!_!last!") do (
rem // This assignment is always one iteration behind:
endlocal & if defined flag set "rest=%%b"
)
rem // This value is available for the next iteration:
set "last=%%~a" & set "flag=#"
rem // Toggle delayed expansion to avoid issues with `!` and `^`:
setlocal EnableDelayedExpansion
)
rem // Revert doubling of quotes:
set "rest=!rest:""="!^" & rem ^"
if defined last set "last=!last:""="!^" & rem ^"
rem // Strip off leading `__`:
set "rest=!rest:~2!"
rem // Return result:
set name
set rest
set last
endlocal
endlocal
pause
在 cmd
batch-file
on windows
中执行此操作的一种方法是在 PowerShell 中使用正则表达式。如果您使用的是受支持的 Windows 系统,则会安装 PowerShell。
请注意,我将结果变量名称 DATE
更改为 THE_DATE
。 DATE 是 cmd
中的自动变量,不应单独使用。
C:>type getlastpart.bat
@ECHO OFF
SET "NAME=text4_text5_text6_text7_2000-01-02"
FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
"'%NAME%' -match '(.*)_(.*)' | Out-Null; $matches[2]"') DO (SET "THE_DATE=%%~A")
ECHO THE_DATE is set to "%THE_DATE%"
C:>CALL getlastpart.bat
THE_DATE is set to "2000-01-02"
C:>echo %THE_DATE%
2000-01-02
我认为这是最简单的方法:
@echo off
setlocal EnableDelayedExpansion
set "dir=text4_text5_text6_text7_2000-01-02"
set "name="
set "last=%dir:_=" & set "name=!name!_!last!" & set "last=%"
set "name=!name:~1!"
echo name="%name%"
echo date="%last%"
此方法通过一个简单的子字符串替换来产生 几个 命令。您可能会通过删除 @echo off
行并在屏幕上查看已执行的代码来欣赏它。有关此方法的进一步说明,请参阅 this thread.
如果你想要更标准的方法,那么这个很简单:
@echo off
setlocal EnableDelayedExpansion
set "dir=text4_text5_text6_text7_2000-01-02"
for %%a in ("%dir:_=.%") do set "last=%%~Xa"
set "last=%last:~1%"
set "name=!dir:_%last%=!"
echo name="%name%"
echo date="%last%"
我有一个包含许多分隔符“_”的文件夹:text4_text5_text6_text7_2000-01-02
我需要从中创建 2 个变量。第一个是从文件夹名称到最后一个分隔符的所有内容。第二个在最后一个分隔符之后:
- %name% = text4_text5_text6_text7
- %日期% = 2000-01-02
日期我有这个代码:
SET DIR = text4_text5_text6_text7_2000-01-02
FOR %%a in (%DIR:_= %) do set DATE=%%a
但我不知道在 %DATE% 之前将 %NAME% 其他所有内容都考虑在内。
我将不胜感激。
您可以将所有值放入字符串数组中。数组的最后一个值必须是 %date%.
@ECHO OFF
SET name=text4_text5_text6_text7_2000-01-02
SET /A id=0
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%a in (%name:_= %) DO (
SET /A id+=1
SET arr[!id!]=%%a
)
REM PRINT ALL VALUES WHERE %id% IS THE LAST ARRAY NUMBER
FOR /L %%i in (1,1,%id%) DO @ECHO !arr[%%i]!
REM PRINT ONLY DATE
@ECHO !arr[%id%]!
ENDLOCAL
如果格式如您所述,最后一个 _
始终包含以下日期:
@echo off
setlocal enabledelayedexpansion
set "name=text4_text5_text6_text7_2000-01-02"
for %%i in (%name:_= %) do set "mydate=%%i"
set "restofline=!name:%mydate%=!"
echo %restofline:~0,-1% %mydate%
此处 %mydate%
是包含日期的变量,%restofline%
包含其余部分。
这里有一个应用有时 so-called 代码注入技术的方法:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define (non-empty) input string here:
set "name=text4_text5_text6_text7_2000-01-02"
rem // Clear variables:
set "rest=" & set "last="
rem // Split off the last `_`-separated item using the code injection technique:
set "rest=%name:_=" & (if defined last set "rest=!rest!_!last!") & set "last=%"
rem // Return result:
set name
set rest
set last
endlocal
pause
相关的控制台输出如下:
name=text4_text5_text6_text7_2000-01-02 rest=text4_text5_text6_text7 last=2000-01-02
要了解它是如何工作的,请将 @echo off
更改为 @echo on
并检查控制台输出。此方法基于 sub-string substitution, and it requires delayed variable expansion.
请注意,如果字符串包含 !
、^
和 "
。
注意,多个连续的分隔符合并为一个,因此像 abc__def__01
这样的字符串将被拆分为 abc_def
和 01
。为避免这种情况并保留分隔符,请将核心代码更改为:
rem // Clear variables:
set "rest=" & set "last=" & set "flag="
rem // Split off the last `_`-separated item using the code injection technique:
set "rest=%name:_=" & (if defined flag (set "rest=!rest!_!last!") else set "flag=#") & set "last=%"
有关此方法的更多信息,请参阅 split string into substrings based on delimiter [DosTips]。
这是一种基于您的代码并使用标准 for
循环的方法:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define (non-empty) input string here:
set "name=text4_text5_text6_text7_2000-01-02"
rem // Reset variables:
set "rest=_" & set "last="
rem // Split off the last `_`-separated item using a `for` loop:
for %%a in ("%name:_= %") do (
rem // This assignment is always one iteration behind:
if defined last set "rest=!rest!_!last!"
rem // This value is available for the next iteration:
set "last=%%a"
)
rem // Strip off leading `__`:
set "rest=%rest:~2%"
rem // Return result:
set name
set rest
set last
endlocal
pause
请注意,对于包含 wildcards 的字符串,如 ?
、*
和 <
、>
,此方法将失败;此外,!
、^
和 "
不得出现在字符串中。
为了至少避免字符串中的 !
、^
和 "
出现问题,请改用这个更健壮但更复杂的代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define input string here:
set "name=text4_text5_text6_text7_2000-01-02"
rem // Reset variables:
set "rest=_" & set "last=" & set "flag="
rem // Double quotes to avoid issues with such:
setlocal EnableDelayedExpansion
set "name=!name:"=""!^" & rem ^"
rem // Split off the last `_`-separated item using a `for` loop:
if defined name for %%a in ("!name:_=" "!") do (
rem // Use `for /F` to transfer string beyond `endlocal` barrier:
for /F "delims=" %%b in ("!rest!_!last!") do (
rem // This assignment is always one iteration behind:
endlocal & if defined flag set "rest=%%b"
)
rem // This value is available for the next iteration:
set "last=%%~a" & set "flag=#"
rem // Toggle delayed expansion to avoid issues with `!` and `^`:
setlocal EnableDelayedExpansion
)
rem // Revert doubling of quotes:
set "rest=!rest:""="!^" & rem ^"
if defined last set "last=!last:""="!^" & rem ^"
rem // Strip off leading `__`:
set "rest=!rest:~2!"
rem // Return result:
set name
set rest
set last
endlocal
endlocal
pause
在 cmd
batch-file
on windows
中执行此操作的一种方法是在 PowerShell 中使用正则表达式。如果您使用的是受支持的 Windows 系统,则会安装 PowerShell。
请注意,我将结果变量名称 DATE
更改为 THE_DATE
。 DATE 是 cmd
中的自动变量,不应单独使用。
C:>type getlastpart.bat
@ECHO OFF
SET "NAME=text4_text5_text6_text7_2000-01-02"
FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
"'%NAME%' -match '(.*)_(.*)' | Out-Null; $matches[2]"') DO (SET "THE_DATE=%%~A")
ECHO THE_DATE is set to "%THE_DATE%"
C:>CALL getlastpart.bat
THE_DATE is set to "2000-01-02"
C:>echo %THE_DATE%
2000-01-02
我认为这是最简单的方法:
@echo off
setlocal EnableDelayedExpansion
set "dir=text4_text5_text6_text7_2000-01-02"
set "name="
set "last=%dir:_=" & set "name=!name!_!last!" & set "last=%"
set "name=!name:~1!"
echo name="%name%"
echo date="%last%"
此方法通过一个简单的子字符串替换来产生 几个 命令。您可能会通过删除 @echo off
行并在屏幕上查看已执行的代码来欣赏它。有关此方法的进一步说明,请参阅 this thread.
如果你想要更标准的方法,那么这个很简单:
@echo off
setlocal EnableDelayedExpansion
set "dir=text4_text5_text6_text7_2000-01-02"
for %%a in ("%dir:_=.%") do set "last=%%~Xa"
set "last=%last:~1%"
set "name=!dir:_%last%=!"
echo name="%name%"
echo date="%last%"