The following DOS script snippet has a bug:
以下DOS脚本片段有一个错误:
if not exist %MyFolder% (
mkdir %MyFolder%
if %errorlevel% GEQ 1 (
rem WARNING: the line above has a bug!
rem %errorlevel% will be the errorlevel
rem of the if statement because of the (parentheses)
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
)
The fix is to use setlocal enabledelayedexpansion
as follows:
解决方法是使用setlocal enabledelayedexpansion,如下所示:
setlocal enabledelayedexpansion
if not exist %MyFolder% (
mkdir %MyFolder%
if !errorlevel! GEQ 1 (
rem WARNING: the line above has a bug!
rem !errorlevel! will be the errorlevel
rem of the if statement because of the (parentheses)
echo Error: Could not create folder %MyFolder%
endlocal & goto AnErrorOccurred
)
)
endlocal
A full explanation of why is available here: Batch file fails to set environment variable within conditional statement
有关原因的完整说明:批处理文件无法在条件语句中设置环境变量
I want to audit my code to find instances of this bug, I figure a Regex would be an appropriate match, but haven't managed to get one working...
我想审核我的代码以找到这个bug的实例,我认为一个正则表达式将是一个合适的匹配,但还没有设法让一个工作...
I think the ingredients should be: Match an environment variable surrounded with %percentsigns% That is inside (parentheses)
我认为成分应该是:匹配一个环境变量包围%percentntsigns%里面(括号)
Any suggestions?
4 个解决方案
#1
grepWin
I would use grepWin. Depending on the number of instances you have to find, you could write a regex that will give you all of them, plus some false positives.
我会用grepWin。根据您必须找到的实例数量,您可以编写一个正则表达式,它将为您提供所有这些实例,以及一些误报。
Example: bug.bat
if not exist %MyVar% echo Hi!
if not exist %MyFolder% (
mkdir %MyFolder%
if %errorlevel% GEQ 1 (
rem WARNING: the line above has a bug!
rem %errorlevel% will be the errorlevel
rem of the if statement because of the brackets
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
)
Then use a regular expression to match all lines that start with if
and have an open parenthesis:
然后使用正则表达式匹配以if开头且具有左括号的所有行:
$ grep "^[ \t]*if.*(" bug.bat
if not exist %MyFolder% (
if %errorlevel% GEQ 1 (
grepWin will show you all the files that match.
grepWin将显示所有匹配的文件。
Percent Symbols
By request:
grep "^[ \t]*if.*%.*%.*(" bug.bat
#2
You can't solve it with Regex, because you can't count the parenthesis with a regular language. For example:
您无法使用Regex解决此问题,因为您无法使用常规语言计算括号。例如:
Stuff (
More Stuff (
Less Stuff )
A %var%
Less Stuff )
There is no (
between the last )
and the variable. Since I can't count how many `( appear before to know if there's one open, I can't do this with regular expressions.
没有(在最后一个之间)和变量。因为我无法计算多少`(以前知道是否有一个打开,我不能用正则表达式做到这一点。
#3
As you can see, he is using ! rather than % even in the rootlevel of the batch. So basically you should be able to alternate every % to an ! for your environmental variables.
如你所见,他正在使用!而不是%甚至在批次的根级别。所以基本上你应该能够将每个%交替到一个!为你的环境变量。
#4
One other way is to use the AND (&&) and OR (||) tests for success (errorlevel 0) or error (errorlevel > 0), as in:
另一种方法是使用AND(&&)和OR(||)测试成功(错误级别0)或错误(错误级别> 0),如:
if not exist %MyFolder% mkdir %MyFolder%|| (
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
I hope this can help.
我希望这可以提供帮助。
And by the way, you do not fail to set the variable, you fail to read it back.
顺便说一句,你没有设置变量,你无法读回它。
What happen is, within parenthesis, using %%'s give you the states which was before you entered the said parenthesis. The only thing I knows work well is the math "set /a toto+=1" which will correctly increment the variable. Otherwise you have two options:
所发生的是,在括号内,使用%%'s给出你进入所述括号之前的状态。我知道唯一合适的工作是数学“set / a toto + = 1”,这将正确地增加变量。否则你有两个选择:
Either use a called function to set the variable or use the setlocal ENABLEDELAYEDEXPANSION statement, as previously stated, and use !!'s within the parenthesis.
如前所述,使用被调用函数来设置变量或使用setlocal ENABLEDELAYEDEXPANSION语句,并在括号内使用!!'。
#1
grepWin
I would use grepWin. Depending on the number of instances you have to find, you could write a regex that will give you all of them, plus some false positives.
我会用grepWin。根据您必须找到的实例数量,您可以编写一个正则表达式,它将为您提供所有这些实例,以及一些误报。
Example: bug.bat
if not exist %MyVar% echo Hi!
if not exist %MyFolder% (
mkdir %MyFolder%
if %errorlevel% GEQ 1 (
rem WARNING: the line above has a bug!
rem %errorlevel% will be the errorlevel
rem of the if statement because of the brackets
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
)
Then use a regular expression to match all lines that start with if
and have an open parenthesis:
然后使用正则表达式匹配以if开头且具有左括号的所有行:
$ grep "^[ \t]*if.*(" bug.bat
if not exist %MyFolder% (
if %errorlevel% GEQ 1 (
grepWin will show you all the files that match.
grepWin将显示所有匹配的文件。
Percent Symbols
By request:
grep "^[ \t]*if.*%.*%.*(" bug.bat
#2
You can't solve it with Regex, because you can't count the parenthesis with a regular language. For example:
您无法使用Regex解决此问题,因为您无法使用常规语言计算括号。例如:
Stuff (
More Stuff (
Less Stuff )
A %var%
Less Stuff )
There is no (
between the last )
and the variable. Since I can't count how many `( appear before to know if there's one open, I can't do this with regular expressions.
没有(在最后一个之间)和变量。因为我无法计算多少`(以前知道是否有一个打开,我不能用正则表达式做到这一点。
#3
As you can see, he is using ! rather than % even in the rootlevel of the batch. So basically you should be able to alternate every % to an ! for your environmental variables.
如你所见,他正在使用!而不是%甚至在批次的根级别。所以基本上你应该能够将每个%交替到一个!为你的环境变量。
#4
One other way is to use the AND (&&) and OR (||) tests for success (errorlevel 0) or error (errorlevel > 0), as in:
另一种方法是使用AND(&&)和OR(||)测试成功(错误级别0)或错误(错误级别> 0),如:
if not exist %MyFolder% mkdir %MyFolder%|| (
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
I hope this can help.
我希望这可以提供帮助。
And by the way, you do not fail to set the variable, you fail to read it back.
顺便说一句,你没有设置变量,你无法读回它。
What happen is, within parenthesis, using %%'s give you the states which was before you entered the said parenthesis. The only thing I knows work well is the math "set /a toto+=1" which will correctly increment the variable. Otherwise you have two options:
所发生的是,在括号内,使用%%'s给出你进入所述括号之前的状态。我知道唯一合适的工作是数学“set / a toto + = 1”,这将正确地增加变量。否则你有两个选择:
Either use a called function to set the variable or use the setlocal ENABLEDELAYEDEXPANSION statement, as previously stated, and use !!'s within the parenthesis.
如前所述,使用被调用函数来设置变量或使用setlocal ENABLEDELAYEDEXPANSION语句,并在括号内使用!!'。