批处理如何用通配符删除变量中指定字符串后的内容
问题根因
Windows批处理原生变量替换语法存在明确限制:
- 仅支持
%VAR:*search=replace%格式的前缀通配逻辑:匹配字符串中第一个出现的search片段及其之前的所有内容,替换为指定内容。这也是VAR=%VAR:*STRING%可以正常删除STRING前所有内容的原因。 - 通配符
*如果放在搜索字符串的末尾、中间位置,不会被解析为通配符,只会被当作普通的*字符做精确匹配。你写的!CURRVARS:REG_*=!实际是在查找内容中字面的REG_*字符串,自然无法匹配REG_SZ、REG_EXPAND_SZ这类注册表类型标识,替换不会生效。
实现方案
原生语法没有提供直接删除指定字符串后所有内容的能力,通用实现思路是逐字符遍历定位目标字符串的起始位置,再截断取该位置之前的内容即可。
针对你读取用户环境变量的场景,不需要写复杂的通用逻辑,注意两个细节就能得到预期结果:
REG QUERY返回的第一行是查询的注册表项路径,不是环境变量值,需要跳过- 逐字符截断当前行内容,直到剩余片段以
REG_开头,截断位置之前的内容就是环境变量名,去掉末尾多余的分隔空格即可
修正后的可运行代码
:CheckEnvironmentVariable Location Variable Value @ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION IF [%1] EQU [System] ( ECHO Querying system ) ELSE ( IF [%1] EQU [User] ( ECHO Querying User Environments REM skip=1跳过第一行的注册表路径输出 FOR /F "usebackq skip=1 tokens=*" %%x IN (`REG QUERY "HKCU\Environment"`) DO ( SET "CURRVARS=%%x" :MatchRegPrefix REM 检查当前字符串是否包含REG_片段,找到第一个REG_的位置 IF "!CURRVARS:REG_=!" NEQ "!CURRVARS!" ( IF "!CURRVARS:~0,4!" NEQ "REG_" ( REM 开头不是REG_就截掉最后一个字符继续判断 SET "CURRVARS=!CURRVARS:~0,-1!" GOTO MatchRegPrefix ) ) REM 截掉REG_及后续内容,再去掉末尾多余空格 CALL :TrimTrailingSpace "!CURRVARS:~0,-4!" CURRVARS ECHO !CURRVARS! ) ) ELSE ( ECHO ERROR ^! Invalid Environment Variable Location "%1" ) ) EXIT /B :TrimTrailingSpace 待处理字符串 输出变量名 SETLOCAL SET "trim_str=%~1" :TrimLoop IF "!trim_str:~-1!" EQU " " SET "trim_str=!trim_str:~0,-1!" & GOTO TrimLoop (ENDLOCAL & SET "%~2=%trim_str%") EXIT /B
通用场景封装
如果需要在其他脚本里复用「删除指定字符串后所有内容」的逻辑,可以封装成通用子函数:
:RemoveAfterMatch 原字符串 匹配目标 输出变量名 SETLOCAL ENABLEDELAYEDEXPANSION SET "source=%~1" SET "target=%~2" REM 计算匹配串长度 SET "t_len=0" :CalTargetLen IF "!target:~%t_len%!" NEQ "" SET /a t_len+=1 & GOTO CalTargetLen SET "pos=0" :FindMatchPos SET "cur_fragment=!source:~%pos%!" REM 匹配到目标串位置 IF "!cur_fragment:~0,%t_len%!" EQU "%target%" GOTO GetPrefix REM 遍历完整个字符串都没匹配到,返回原内容 IF "!cur_fragment!" EQU "" GOTO NoMatch SET /a pos+=1 GOTO FindMatchPos :GetPrefix SET "result=!source:~0,%pos%!" GOTO ReturnResult :NoMatch SET "result=%source%" :ReturnResult (ENDLOCAL & SET "%~3=%result%") EXIT /B
调用示例:
SET "testStr=PathREG_EXPAND_SZ%SystemRoot%" CALL :RemoveAfterMatch "!testStr!" "REG_" output ECHO !output! REM 输出结果为Path
内容的提问来源于stack exchange,提问作者Andre B
相关产品推荐
相关产品推荐

