【问题标题】:Extracting file name from array element in batch批量从数组元素中提取文件名
【发布时间】:2016-08-19 14:02:36
【问题描述】:

我有一个这样的环境变量

set BINARY[0]=C:\binary.bin

我试图从中提取完整的文件名

set "x=0"
:binloop
if defined BINARY[%x%] (
    call echo %%BINARY[%x%]%%
    FOR %%i IN ("%%BINARY[%x%]%%") DO (
         set FNAME=%%~nxi
    )
    set /a "x+=1"
    GOTO binloop
)
rem ...

但是由于某种原因,它尝试这样做:

set FNAME=%BINARY[0]% 

而不是

set FNAME=binary.bin

代码有什么问题,为什么?

【问题讨论】:

标签: windows batch-file batch-processing


【解决方案1】:

打开命令提示符窗口,运行 set /? 并阅读输出帮助页面,说明何时以及如何在代码块中为命令 IFFOR 使用延迟扩展>.

批处理文件中的%% 被解释为文字百分比字符,这就是为什么在命令提示符窗口中直接执行的命令中的循环变量必须仅用一个百分号指定,而批处理文件中的相同循环引用循环变量时需要两个百分号。

当 Windows 命令处理器遇到一个标记命令块开始的左括号时,它会搜索匹配的右括号并将所有使用语法 %VariableName% 的环境变量引用替换为变量的当前值或不替换以防万一的变量不存在。然后在解析整个命令块之后,执行 IFFOR 并使用已经预处理的命令块一次或多次。

你可以使用

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BINARY[1]=C:\binary1.bin"
set "BINARY[0]=C:\binary0.bin"
set "x=0"

:binloop
if defined BINARY[%x%] (
    call echo %%BINARY[%x%]%%
    for %%i in ("!BINARY[%x%]!") do (
         set FNAME=%%~nxi
         set FNAME
    )
    set /a "x+=1"
    goto binloop
)
endlocal

哪个输出

C:\binary0.bin
FNAME=binary0.bin
C:\binary1.bin
FNAME=binary1.bin

命令行

call echo %%BINARY[%x%]%%

有点特别。此行在执行命令 IF

之前进行了预处理
call echo %BINARY[0]%

分别在第二次运行时

call echo %BINARY[1]%

通过使用命令CALL,单个命令行像子程序或另一个批处理文件一样被处理,这意味着该行被再次预处理,导致执行

 echo C:\binary0.bin

并在第二次运行时执行

 echo C:\binary1.bin

这就是这里的输出符合预期的原因。但是FOR中的环境变量引用没有双重预处理。

最好是以下代码:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BINARY[1]=C:\binary1.bin"
set "BINARY[0]=C:\binary0.bin"

for /F "tokens=1* delims==" %%I in ('set "BINARY[" 2^>nul') do (
    set "FNAME=%%~nxJ"
    set FNAME
)

endlocal

当参数/A/P被使用且参数中不包含等号时,命令set输出所有变量及其名称和等号以及以指定字符串开头的值按字母顺序排列的列表。所以

的输出
set "BINARY[" 2>nul

在命令中使用 FOR

BINARY[0]=C:\binary0.bin
BINARY[1]=C:\binary1.bin

FOR 循环处理,该循环根据 tokens=1* delims== 的第一次出现等号将每行拆分为两个字符串。第一个字符串是分配给循环变量I 的变量名。第二个字符串是分配给循环变量J的第一个等号之后的所有内容,是ASCII表中的下一个字符。

2>nul 用于抑制命令 SETSTDERR 输出的错误消息,如果没有,则将其重定向到设备 NUL在任何情况下,环境变量的名称都以BINARY[ 开头。重定向运算符> 必须用^ 转义,否则命令处理器将退出此行的批处理,因为2>nul 导致FOR 命令行在此位置出现语法错误。

注意:由于命令 SET 按字母顺序输出,环境变量BINARY[10]BINARY[0] 之后和BINARY[1]BINARY[2] 之前输出。因此,如果顺序很重要,则需要第一个批处理解决方案,或者使用方括号中的数字创建环境变量,它们的数字都相同,前导零,即 00000, 00001, ..., 00002, 00010, 00011, 。 ..

要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

另请参阅有关 Using command redirection operators 的 Microsoft 文章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多