批处理文件中最佳的子字符串处理方式是什么?

226

我想要获取当前正在运行的批处理文件的名称,不包括文件扩展名。

感谢这个链接,我已经有了带扩展名的文件名...但是,在批处理文件中进行子字符串操作的最佳方法是什么?

还是有另一种方法可以获取没有扩展名的文件名吗?

在这种情况下,可以安全地假定为 3 个字母的扩展名。

3个回答

449

获取批处理文件名最简单的方法是使用%~n0

@echo %~n0

将输出当前正在运行的批处理文件的名称(不包括扩展名),除非它是通过call调用的子例程。此类路径名称的“特殊”替换的完整列表可以在help for中找到,在帮助的最后:

此外,FOR变量引用的替换已进行增强。 您现在可以使用以下可选语法:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

这些修饰符可以组合使用,以获得复合结果:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only
为了准确回答你的问题,使用 :~start,length 表示法可以进行子字符串操作:
%var:~10,5%

从环境变量%var%中提取第10个位置开始的5个字符。

注意:字符串的索引从0开始,因此第一个字符在位置0,第二个字符在1等等。

要获取参数变量%0%1等的子字符串,您需要先使用set将它们分配给普通环境变量:

:: Does not work:
@echo %1:~10,5

:: Assign argument to local variable first:
set var=%1
@echo %var:~10,5%

语法更加强大:

  • %var:~-7%%var%中提取最后7个字符
  • %var:~0,-4%将提取除了最后四个字符之外的所有字符,这也将使你摆脱文件扩展名(假设在句点[.]之后有三个字符)。

有关该语法的详细信息,请参见help set


36
提取子字符串也不能和FOR循环变量一起使用,所以你需要按照以下方式操作(代码中的\r\n表示换行符,因为SO似乎不允许在注释中换行):setlocal ENABLEDELAYEDEXPANSION \r\n for /f %%s in ('set') do ( \r\n set tmp=%%s \r\n echo !tmp:~-3! \r\n ) - Fr0sT
5
@Adrian 为什么不呢?“FOR”在批处理文件中是一种基础结构,可以执行各种各样的任务。另外,还有一种使用子程序应对任务的方法,即for /f %%s in ('set') do call :DoSmth "%%s" \r\n ... \r\n :DoSmth \r\n set var=%1 \r\n echo %var:~1,3% - Fr0sT
1
@Phate01,不要使用%date%来构建特定格式的日期。该格式是特定于用户文化背景的,可能会发生变化。相反,使用WMI获取日期和时间以便以一种有用的格式呈现,而不依赖于用户的设置。此外,我不确定这个评论在这里的作用是什么,因为这个问题与日期或时间无关。 - Joey
1
其实你是对的,我猜我想评论一个不同的问题 :) - Phate01
@Fr0sT 是的,它可以工作,但你必须使用 setlocal 并启用延迟扩展。 - user2262111
显示剩余4条评论

42

上面的解释得很好!

对于所有可能像我一样遇到问题在本地化的Windows系统中(我的是斯洛伐克语的XP系统)运行时,你可以尝试用!替换%

所以:

SET TEXT=Hello World
SET SUBSTRING=!TEXT:~3,5!
ECHO !SUBSTRING!

32
请注意,这个命令只能在执行了setlocal ENABLEDELAYEDEXPANSION命令之后才能生效。 - Fr0sT
尝试使用以下编程代码:SET TEXT="<Hello World>"SET SUBSTRING=!TEXT:~1,-1!SET SUBSTRING=%TEXT:~1,-1%,然后使用ECHO !SUBSTRING!ECHO %SUBSTRING%命令输出结果。 - Sasha Bond
如何在使用~3时使用~othervar替代它?这对我不起作用。 - johny why

13
作为Joey答案的附加信息,这并没有在set /? 或者 for /?的帮助中描述。 %~0会扩展成自身批处理文件的名称,就是你键入的那个名字。 所以如果你启动了你的批处理,它会被扩展成:
%~0   - mYbAtCh
%~n0  - mybatch
%~nx0 - mybatch.bat

但是有一个例外情况,将子程序中的展开可能会失败。

echo main- %~0
call :myFunction
exit /b

:myFunction
echo func - %~0
echo func - %~n0
exit /b

这会导致

main - myBatch
Func - :myFunction
func - mybatch

在一个函数中,%~0 总是扩展为函数名,而不是批处理文件的名称。
但是,如果您使用至少一个修改器,它将再次显示文件名!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接