我正在为Windows命令行构建一个脚本,我尝试在 FOR 循环中检查一些文件名,然后将部分文件名剥离到变量中以供进一步使用。基本上,我想要发生的是:
通过一些试验和错误以及一些在线搜索,我已经到了这一点(这仍然没有做我想要的):
FOR /F "tokens=1-2 delims=." %%M IN ('DIR /b %VECTOR_WORKDIR%\*.osm.pbf') DO (
SET VECTOR_CURRENT_MAP2=%%M
ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
SET LAST_BIT_TEMP=!VECTOR_CURRENT_MAP2:~-7!
ECHO !LAST_BIT_TEMP! >> %VECTOR_LOGFILE%
SET LAST_BIT=!LAST_BIT_TEMP: =!
ECHO !LAST_BIT! >> %VECTOR_LOGFILE%
IF !LAST_BIT!=="-latest" (
SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-8!
ELSE
SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!
)
ECHO !VECTOR_CURRENT_MAP3! >> %VECTOR_LOGFILE%
)
这导致日志文件中的这些行,文件basse-normandie-latest.osm.pbf
:
basse-normandie-latest
-latest
-latest
ECHO is on.
第一个回显是正确的,尽管文件名有尾随空格。 (所以实际上它是“basse-normandie-latest”。)
第二个回声似乎没有考虑到这个训练空间,因为它正确地给出了“-latest”作为最后7个字符。这个echo也有一个尾随空格(实际上它是“-latest”。)
第三个回显是尝试从变量中清除空格(通过使用“:=”),但这会导致另一个尾随空格。 (所以实际上它是“最新的”。)
IF语句之后的最终回显(我尝试从文件名中删除“-latest”部分),导致“ECHO打开”。
我在脚本的顶部声明了SETLOCAL enabledelayedexpansion enableextensions
。
有关如何使这项工作的任何想法,即摆脱尾随空格,使比较工作?
提前感谢任何指向正确的方向!
答案 0 :(得分:0)
像
这样的行ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
导致将环境变量VECTOR_CURRENT_MAP2
的值附加到文件名,文件名存储在具有尾随空格的环境变量VECTOR_LOGFILE
中,因为在重定向运算符之前有一个空格 >>
由Windows命令处理器解释为要通过命令 ECHO 输出的字符串的一部分。必须删除此空间才能将文件名重定向到日志文件中,而不会有尾随空格。
一般情况下,如果变量字符串以空格结尾并且数字是有效的句柄号(如{{1}),则将变量字符串重定向到文件中且变量字符串和重定向运算符之间没有空格是至关重要的}或 1
或 2
。有几种解决方案可以解决这个问题,例如指定重定向左命令 ECHO ,即
3
但是在这里使用延迟扩展时,可以安全地在末尾附加重定向,而感叹号和>>%VECTOR_LOGFILE% ECHO !VECTOR_CURRENT_MAP2!
之间没有空格,即
>>
Windows命令处理器忽略重定向运算符后的空间,因此可以保留,但许多具有良好语法突出显示的批处理文件程序员(如我)在重定向后不插入空格操作
在使用命令 IF 比较字符串并将一个字符串用双引号括起来时,这总是一个好主意,必须确保另一个字符串也用双引号括起来。在比较字符串之前,命令 IF 不会删除双引号。双引号是比较字符串的一部分。
条件
ECHO !VECTOR_CURRENT_MAP2!>> %VECTOR_LOGFILE%
仅当分配给环境变量IF !LAST_BIT!=="-latest"
的字符串与周围的引号一起时才是真的,这与批处理代码的情况绝不相同,因此条件永远不会成立。
正确的是:
LAST_BIT
无需使用命令 DIR 来搜索目录中带有模式的文件,因为命令 FOR 旨在完成此任务。处理输出命令 DIR 是 FOR 的扩展,仅当默认情况下启用了命令扩展时才可用。
文件扩展名由Microsoft定义为文件名中最后一个点之后的所有内容。因此,文件的文件扩展名分别为IF "!LAST_BIT!"=="-latest"
pbf
,.pbf
属于文件名。
命令 FOR 提供了几个修饰符来获取文件或目录名的特定部分。在命令提示符窗口.osm
中运行时,帮助输出到控制台窗口中解释了这些修饰符。使用for /?
输出命令 CALL 的帮助解释了批处理文件或子程序的处理参数(批处理文件中嵌入的批处理文件)的相同内容。
删除了所有错误的代码:
call /?
更容易使用此代码使用命令 SET 的字符串替换功能,即在字符串内搜索不区分大小写的所有字符串,并将其替换为另一个字符串,该字符串也可以是空字符串。
FOR %%M IN (*.osm.pbf) DO (
SET "VECTOR_CURRENT_MAP2=%%~nM"
SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
SET "LAST7CHARS=!VECTOR_CURRENT_MAP2:~-7!"
ECHO !LAST7CHARS!>>%VECTOR_LOGFILE%
IF "!LAST7CHARS!" == "-latest" (
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-7!"
) ELSE (
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!"
)
ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)
FOR %%M IN (*.osm.pbf) DO (
SET "VECTOR_CURRENT_MAP2=%%~nM"
SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:-latest=!"
ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)
在Windows命令处理器执行时被替换为没有驱动器,路径和文件扩展名的文件名,而%%~nM
为您的示例。
不需要的文件名部分basse-normandie-latest.osm
将被删除,两个批处理代码块中的下一行将从文件名字符串中删除最后4个字符。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
.osm
echo /?
for /?
if /?
阅读问题Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案,以解释为什么我在每一行都使用set /?
为行环境变量分配值字符串,因为尾随空格对您的任务至关重要。