在最后 space 之后将变量减少到所有
Pare down a variable to all after last space
我有以下内容,将文件夹名称 (FOLDER) 缩减为仅第一个 space (tmpFOLDER) 之前的所有文本。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
for %%I in (..) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set tmpFOLDER=%%a
ECHO %FOLDER%
ECHO %tmpFOLDER%
popd
endlocal
主要请求:
有没有办法反过来做?
文件夹名称 (%FOLDER%):史密斯 - 约翰
当前示例 (%tmpFOLDER%):Smith
所需示例 (%tmpFOLDER%):John
中学:
有没有办法对文件执行此操作,同时忽略任何文件类型(即 .txt)?
文件名 (%FILE%):“史密斯 - John.txt”
示例当前 (%tmpFILE%):史密斯
所需示例 (%tmpFILE%):John
遍历文件或目录名的话for /F
loop cannot extract tokens counted from the end of a string. However, you could use a standard for
loop:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Retrieve base name of grand-parent directory of this script:
for /D %%I in ("%~dp0..") do set "FOLDER=%%~nI"
echo Old name: "%FOLDER%"
set "PREV=" & set "COLL="
rem /* Unnecessary loop iterating once and returning the whole directory name;
rem it is just here to demonstrate how to handle also more than one names: */
for /F "delims= eol=|" %%L in ("%FOLDER%") do (
rem // Store current name strng and reset some interim variables:
set "NAME=%%L" & set "PREV=" & set "COLL= "
rem // Toggle delayed expansion to avoid issues with `!` and `^`:
setlocal EnableDelayedExpansion
rem // Ensure to have each space-separated word quoted, then loop through them:
for %%K in ("!NAME: =" "!") do (
rem /* Build new buffer by concatenating word from previous loop iteration,
rem then transfer it over `endlocal` barrier (localised environment): */
for %%J in ("!COLL! !PREV!") do (
rem // Store current word in an unquoted manner:
endlocal & set "ITEM=%%~K"
rem // Store current buffer, store current word for next iteration:
set "COLL=%%~J" & set "PREV=%%~K"
setlocal EnableDelayedExpansion
)
)
endlocal
)
rem // Retrieve final result:
set "RESULT=%COLL:~3%"
echo New name: "%RESULT%"
echo Last word: "%PREV%"
endlocal
exit /B
这种方法returns删除了最后一个单词的名字以及名字的最后一个单词。
另一种解决方案是有时所谓的代码注入技术,它需要 delayed variable expansion 并且很难理解:
setlocal EnableDelayedExpansion
echo Old name: "%FOLDER%"
set "RESULT=%FOLDER: =" & set "RESULT=!RESULT!!ITEM!" & set "ITEM= %"
echo New name: "%RESULT%"
echo Last word: "%ITEM:* =%"
endlocal
请注意,当输入字符串包含 !
、^
或 "
(但后者无论如何不能出现在文件或目录名称中)时,这将失败。
另一种方法是用 \
替换空格,然后(误)使用 ~
-modifiers,这是可行的,因为纯文件或目录名称不能包含 \
它自己的:
echo Old name: "%FOLDER%"
rem // Precede `\` to make pseudo-path relative to root, then replace each ` ` by `\`:
for %%I in ("\%FOLDER: =\%") do (
rem // Let `for` meta-variable expansion do the job:
set "RESULT=%%~pI"
set "LAST=%%~nxI"
)
rem // Remove leading and trailing `\`; then revert replacement of ` ` by `\`:
set "RESULT=%RESULT:~1,-1%"
echo New name: "%RESULT:\= %"
echo Last word: "%LAST%"
这种方法甚至不需要delayed expansion。
我有以下内容,将文件夹名称 (FOLDER) 缩减为仅第一个 space (tmpFOLDER) 之前的所有文本。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
for %%I in (..) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set tmpFOLDER=%%a
ECHO %FOLDER%
ECHO %tmpFOLDER%
popd
endlocal
主要请求:
有没有办法反过来做?
文件夹名称 (%FOLDER%):史密斯 - 约翰
当前示例 (%tmpFOLDER%):Smith
所需示例 (%tmpFOLDER%):John
中学:
有没有办法对文件执行此操作,同时忽略任何文件类型(即 .txt)?
文件名 (%FILE%):“史密斯 - John.txt”
示例当前 (%tmpFILE%):史密斯
所需示例 (%tmpFILE%):John
遍历文件或目录名的话for /F
loop cannot extract tokens counted from the end of a string. However, you could use a standard for
loop:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Retrieve base name of grand-parent directory of this script:
for /D %%I in ("%~dp0..") do set "FOLDER=%%~nI"
echo Old name: "%FOLDER%"
set "PREV=" & set "COLL="
rem /* Unnecessary loop iterating once and returning the whole directory name;
rem it is just here to demonstrate how to handle also more than one names: */
for /F "delims= eol=|" %%L in ("%FOLDER%") do (
rem // Store current name strng and reset some interim variables:
set "NAME=%%L" & set "PREV=" & set "COLL= "
rem // Toggle delayed expansion to avoid issues with `!` and `^`:
setlocal EnableDelayedExpansion
rem // Ensure to have each space-separated word quoted, then loop through them:
for %%K in ("!NAME: =" "!") do (
rem /* Build new buffer by concatenating word from previous loop iteration,
rem then transfer it over `endlocal` barrier (localised environment): */
for %%J in ("!COLL! !PREV!") do (
rem // Store current word in an unquoted manner:
endlocal & set "ITEM=%%~K"
rem // Store current buffer, store current word for next iteration:
set "COLL=%%~J" & set "PREV=%%~K"
setlocal EnableDelayedExpansion
)
)
endlocal
)
rem // Retrieve final result:
set "RESULT=%COLL:~3%"
echo New name: "%RESULT%"
echo Last word: "%PREV%"
endlocal
exit /B
这种方法returns删除了最后一个单词的名字以及名字的最后一个单词。
另一种解决方案是有时所谓的代码注入技术,它需要 delayed variable expansion 并且很难理解:
setlocal EnableDelayedExpansion
echo Old name: "%FOLDER%"
set "RESULT=%FOLDER: =" & set "RESULT=!RESULT!!ITEM!" & set "ITEM= %"
echo New name: "%RESULT%"
echo Last word: "%ITEM:* =%"
endlocal
请注意,当输入字符串包含 !
、^
或 "
(但后者无论如何不能出现在文件或目录名称中)时,这将失败。
另一种方法是用 \
替换空格,然后(误)使用 ~
-modifiers,这是可行的,因为纯文件或目录名称不能包含 \
它自己的:
echo Old name: "%FOLDER%"
rem // Precede `\` to make pseudo-path relative to root, then replace each ` ` by `\`:
for %%I in ("\%FOLDER: =\%") do (
rem // Let `for` meta-variable expansion do the job:
set "RESULT=%%~pI"
set "LAST=%%~nxI"
)
rem // Remove leading and trailing `\`; then revert replacement of ` ` by `\`:
set "RESULT=%RESULT:~1,-1%"
echo New name: "%RESULT:\= %"
echo Last word: "%LAST%"
这种方法甚至不需要delayed expansion。