首页 > 解决方案 > 比较字符串时遇到问题

问题描述

作为学习 Windows 批处理编程的练习,我正在尝试创建一个批处理文件,该文件将处理文件夹中的所有 SCSS 文件并将它们编译成 CSS。我在尝试过滤掉所有以下划线开头的文件时遇到了一个问题,因为这些文件是仅用于 @import 语句的片段。

我到目前为止的批处理文件是:

@echo off
SETLOCAL EnableDelayedExpansion
FOR /R "D:\Jaye\Programming\Web\Project\scss" %%G IN (*.scss) DO (
    SET name=%%~nG
    echo !name!
    SET firstChar=!name:~0,1!
    echo !firstChar!
    if !firstChar! == "_" (
        echo "Dont process this file"
    )
)
ENDLOCAL

...\Project\scss 文件夹包含以下四个文件:

main.scss
menus.scss
content.scss
_uiColors.scss

我得到的输出是:

content
c
main
m
menus
m
_uiColors
_

这里的重要问题是 _uiColors.scss 文件没有触发 bat 文件第 9 行的 if 语句。根据输出,我可以看到它正在按预期将 firstChar 变量设置为下划线,但是当在 if 语句中进行比较时,某些东西并没有像我预期的那样进行评估。我想知道为什么"_"=="_"似乎评估为假(可能是类型不匹配吗?)然后我可能会尝试修复它。

谢谢

编辑(有答案):由于 Mofi 和 Gerhard 的回答,我现在可以正常工作了。多谢你们。我遇到的问题是由于我基于以前使用其他更现代语言的经验做出的假设,我在处理字符串时错误地使用了引号。

标签: batch-filesass

解决方案


我对Windows 批处理文件中与 NEQ、LSS、GTR 等等效的符号的回答详细解释了如何通过命令IF完成字符串比较,其中包括比较字符串的周围环境"。因此,条件if !firstChar! == "_"永远不会为真,因为左侧的字符串总是只有一个字符,"而右侧的字符串只有三个字符。

我建议这项任务:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "D:\Jaye\Programming\Web\Project\scss\*.scss" /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /V "\\_[^\\]*$"') do (
    rem Do something with file name assigned to loop variable I.
    echo File to process is: "%%I"
)
endlocal

命令FOR在后台启动另一个命令进程,其中%ComSpec% /c的命令行'作为附加参数附加。因此在后台执行是在安装 Windows 的情况下C:\Windows

C:\Windows\System32\cmd.exe /c dir "D:\Jaye\Programming\Web\Project\scss\*.scss" /A-D /B /S 2>nul | %SystemRoot%\System32\findstr.exe /R /V "\\_[^\\]*$"

命令DIR搜索

  • 在指定目录D:\Jaye\Programming\Web\Project\scss
  • 及其所有子目录,因为选项/S
  • 由于选项/A-D(属性不是目录)的文件
  • 匹配通配符模式*.scss
  • 由于 option 以裸格式输出找到的文件名,/B这意味着只有文件名和文件扩展名,并且由于 option 具有完整路径/S

DIR输出的文件名被重定向到FINDSTR,它使用正则表达式搜索在最后一个反斜杠字符后面带有下划线的行,这意味着在文件名的开头并输出反转的结果,即文件名不以开头的所有行一个下划线。

DIR在找不到与搜索条件匹配的文件时处理STDERR输出的错误消息通过将其重定向2>nul到设备NUL来抑制。

阅读有关使用命令重定向运算符2>nul的 Microsoft 文档,了解和的说明|当 Windows 命令解释器在执行命令FOR之前在后台启动的单独命令进程中执行嵌入式命令行时,重定向运算符>|必须^FOR命令行上使用脱字符号转义以被解释为文字字符。

带有选项的命令FOR/F捕获写入以处理已启动后台命令进程的STDOUTcmd.exe的输出,并在启动后自行终止后逐行处理捕获的输出。

FOR总是忽略空行,这里不会出现。默认情况下,所有其他行都使用普通空格和水平制表符作为分隔符拆分为子字符串。此处不需要此行拆分行为,因为*.scss文件名中可能存在带有空格的文件。出于这个原因,该选项delims=用于定义一个空的分隔符列表,该列表禁用行拆分行为。

带有选项的FOR/F也会忽略行拆分后的第一个子字符串以分号开头的行,因为;它是默认的行尾字符。文件名可以以分号开头。但是在这种情况下, DIR输出的文件名总是带有完整路径,因此任何完全限定的文件名都不可能以分号开头。所以eol=;在这种情况下可以保留默认值。

此解决方案的优点是*.scss通常包含一个或多个文件!的处理也正确,因为这里不需要延迟环境变量扩展。FINDSTR进行文件名过滤。

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

  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • rem /?
  • setlocal /?

推荐阅读