批处理文件"不平衡的括号"

时间:2016-07-14 13:01:27

标签: windows batch-file windows-7

所以我有这个程序,我试图制作:

var iOSRegex = /iPad|iPhone|iPod/g;
var ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B137 Safari/601.1";

var first = iOSRegex.test(ua);
console.log(ua.match(iOSRegex));
var second = iOSRegex.test(ua);
var third = iOSRegex.test(ua);
var fourth = iOSRegex.test(ua); // This evaluates to false.

console.log(first + ' -- ' + second + ' -- ' + third + ' -- ' + fourth);
/*
Result 
[ 'iPhone', 'iPhone' ]
true -- true -- true -- false
*/

//@echo off @title Calculate Caloric Needs set /p name=What is the name of the individual in question? CLS :START set /p sex=Is %name% a M(ale) or F(emale)? (M/F) CLS if NOT %sex%==M if NOT %sex%==F ( echo Invalid Selection...Try Again.... goto START ) set /p w=What is the target weight of %name%? CLS set /p h=What is the height of %name% IN INCHES? CLS set /p a=What is the age of %name%? CLS if %sex%==M set /a result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%) if %sex%==F set /a result=655+(4.35*%w%)+(4.7*%h%)-(4.7*%a%) echo %result% is the caloric intake for %name%. pause exit 已被禁用,以便进行问题排查。

这是一个简单的计划,旨在进行一些卡路里摄入计算,这些计算有点难以逐一进行。

每当我达到需要进行算术运算的程度时,就会发生以下两种情况之一:

  1. 如果我将@echo off语句包装在set /a块中,程序将意外退出而不显示错误消息。
  2. 如果我没有将所有内容全部放在一行(就像上面发布的示例代码中那样),那么我会收到消息if %sex%==M ( CODE HERE )而无需进一步解释(感谢Windows ...)。
  3. 据我所知,从数学上讲,括号是完全平衡的。

    我试过了:

    • Unbalanced Parenthesis语句包含在set /a""[]set /a "result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)"
    • 转义算术set /a [result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)]
    • 中使用的部分或全部括号
    • 为了测试set /a result=66 + ^(6.23 * %w%^) + ^(12.7 * %h%^) - ^(6.8 * %a%^)而减少括号数量。 如果我完全使用set /a result=66 + (6.23 * %w%),我实际上可以将该语句包装在set /a result=66 + (6.23 * %w%)块中并让它实际返回错误值。虽然错误仍然是if ( CODE HERE ) ...
    • 延长或缩短算术本身Unbalanced Parenthesis VS中的空格数。 set /a result=66+(6.23*%w%)+(12.7*%h%)-(6.8*%a%)
    • 上述
    • 的所有组合

    所以我对可能导致这种奇怪行为的原因感到茫然。

2 个答案:

答案 0 :(得分:2)

您收到的错误消息在您的情况下非常混乱,因为set /A命令行中的括号是平衡的,并且如果整个命令行没有放在带括号的代码块中,则会像这样工作在其自己的。无论如何,将整个set /A表达式放在引号之间总是一个好主意,因此括号和其他特殊字符都不会引起麻烦。
方括号对set /A没有任何特殊含义。

无论如何,错误的根本原因是您使用小数,尽管set /A仅支持32位空间中的有符号整数算术(请参阅{的帮助{1}})。在命令提示符窗口中键入set /?,您将收到相同的错误消息;但删除set /A (1.2*3),一切都会好起来的。

一种可能的解决方法是使用类似定点算术的东西,因此在计算过程中将所有内容乘以10的整数幂,并最终将结果除以10的相同幂,或换句话说,移动小数在进行计算之前指向右边并在之后将其移回。

这就是它的样子(我还修复了你的代码中的一些其他问题,但请看下面的内容):

.

这是我修正的:

  • @echo off @title Calculate Caloric Needs cls set "name=them" set /P "name=What is the name of the individual in question? " :START set "sex=" set /P "sex=Is %name% a M(ale) or F(emale)? (M/F) " if /I not "%sex%"=="M" if /I not "%sex%"=="F" ( echo Invalid Selection... Try Again... goto :START ) set "w=0" set /P "w=What is the target weight of %name%? " set "h=0" set /P "h=What is the height of %name% IN INCHES? " set "h=%h%." & rem // append a decimal dot to entry in `h` set "mil=1%h:*.=%" & rem // store everything behind first dot in `mil`, prepend `1` set /A "h+=0, mil+=0" & rem // convert `h` to integer, dismiss fractional part set "mil=%mil%000" & rem // pad trailing zeros to `mil` set "mil=%mil:~,4%" & rem // extract first four numerals from `mil` set /A "mil+=5" & rem // add `5` to `mil` for rounding if %mil:~,1% GTR 1 set /A "h+=1" & rem // regard carry of previous addition in `h` set "h=%h%%mil:~-3,-1%" & rem /* append second and third numeral of `mil` to `h`, rem hence dismissing previously prepended `1`; rem so `h` holds the height in 100ths of inches now */ set "a=0" set /P "a=What is the age of %name%? " rem // quotation marks avoid trouble with parenthesis or other characters; rem /* all original constants are multiplied by `1000` to avoid fractional parts, rem except the factor at `h` which is multiplied by `10` only due to above rem implicit multiplication of `h` by 100, then `500` is added for rounding, rem and finally, the result is divided by `1000` to remove the previous factors: */ if /I "%sex%"=="M" ( set /A "result=(66000+(6230*%w%)+(127*%h%)-(6800*%a%)+500)/1000" ) else if /I "%sex%"=="F" ( set /A "result=(655000+(4350*%w%)+(47*%h%)-(4700*%a%)+500)/1000" ) echo %result% is the caloric intake for %name%. pause exit /B set语法得到改进,因此整个表达式都在引号之间,因此您可以避免使用特殊字符,并且您可以清楚地看到是否有任何尾随的空格; < / LI>
  • 初始化任何提示值以避免在用户只按 RETURN ;
  • 时采用先前的值
  • 对性别条目的set /P查询进行了更正,以便通过添加开关if使它们现在不区分大小写,并且通过附加比较来确保测试变量为空时它们不会造成麻烦引号中的表达;
    顺便说一下,您可能对这些单键条目的/I命令感兴趣,因为它甚至不接受任何其他字符;
  • 以英寸为单位的高度条目choice的值由于所述定点算术而被转换为100英寸(但是重量h和年龄w仍然被视为整数);这是它的工作原理:
    • a:在set "h=%h%."中的条目附加一个点,以确保至少有一个;
    • h:将set "mil=1%h:*.=%"中第一个点后的所有内容存储到h(小数部分),并将mil添加到结果中,以便不丢失任何前导零(一旦将其转换为数字,则对于小数部分是重要的;
    • 1:将set /A "h+=0, mil+=0"h转换为数值(整数);这将所有内容转换为第一个非数字数字为一个数字,忽略前导空格,但是关于符号mil / +(尽管它们不相关,因为这里不需要);
    • -:将3个尾随零附加到小数部分(前置set "mil=%mil%000"仍然存在,因此始终至少有4位数字);
    • 1:提取前4个字符(所以前置set "mil=%mil:~,4%"加上3个字符);
    • 1:添加set /A "mil+=5",如果最后一个数字为5或更多,则会出现一个进位,因此倒数第二个数字会发生;
    • 5:如果进位超过小数部分,则在if %mil:~,1% GTR 1 set /A "h+=1"中增加整数部分;
    • h:连接set "h=%h%%mil:~-3,-1%"的整数部分和h中小数部分的倒数第二个到倒数的范围,并将其存储在{{1}中}};
  • mil公式中的所有常数乘以h,小数点消失,但result因子仅乘以1000,因为h已经是原始高度值的100倍;之后结果除以10;添加h只是在1000关于除法时添加500,而是在将0.51000之前的小数部分进行整理由于整数除法而迷失;
  • .5命令被.9*替换为终止批处理文件,但不是拥有exit实例;

请注意,exit /Bcmd//等评论在批处理文件中没有特殊含义。评论或评论由/*声明给出。我在*/中使用了斜杠式注释,只是为了在这个网站上突出显示一些很酷的语法......

更新

根据comment by the original poster,结果本身应该是一个小数,所以我稍微修改了一下脚本(下面的描述如下):

rem

这就是我所做的:

  • 基本计算公式仍然相同,只是这次省略了rem的除法,并且@echo off @title Calculate Caloric Needs cls set "name=them" set /P "name=What is the name of the individual in question? " set "male=" choice /C MF /M "Is %name% a M(ale) of F(emale)? " if not ErrorLevel 2 set "male=Flag" set "w=0" set /P "w=What is the target weight of %name% IN POUNDS? " set "h=0" set /P "h=What is the height of %name% IN INCHES? " set "h=%h%." & rem // append a decimal dot to entry in `h` set "mil=1%h:*.=%" & rem // store everything behind first dot in `mil`, prepend `1` set /A "h+=0, mil+=0" & rem // convert `h` to integer, dismiss fractional part set "mil=%mil%000" & rem // pad trailing zeros to `mil` set "mil=%mil:~,4%" & rem // extract first four numerals from `mil` set /A "mil+=5" & rem // add `5` to `mil` for rounding if %mil:~,1% GTR 1 set /A "h+=1" & rem // regard carry of previous addition in `h` set "h=%h%%mil:~-3,-1%" & rem /* append second and third numeral of `mil` to `h`, rem hence dismissing previously prepended `1`; rem so `h` holds the height in 100ths of inches now */ set "a=0" set /P "a=What is the age of %name% IN YEARS? " rem // quotation marks avoid trouble with parenthesis or other characters; rem /* all original constants are multiplied by `1000` to avoid fractional parts, rem except the factor at `h` which is multiplied by `10` only due to above rem implicit multiplication of `h` by 100, then `500` is added for rounding, rem and finally, the result is divided by `1000` to remove the previous factors: */ if defined male ( set /A "result=66000+(6230*%w%)+(127*%h%)-(6800*%a%)+5" ) else ( set /A "result=655000+(4350*%w%)+(47*%h%)-(4700*%a%)+5" ) echo %result:~,-3%.%result:~-3,-1% is the caloric intake for %name%. pause exit /B 被添加到舍入而不是1000的结果中;但是,为了显示结果,最后一个数字被删除,并且在剩下的最后两个数字之前插入一个小数点5,因此结果有两个小数位;
  • 性别条目现在由500命令按照此答案的原始版本(见上文)中的建议完成,因此不再需要捕获无效结果,因为.只接受预定义的键或字符;

答案 1 :(得分:1)

根据@ aschipfl的回复,这是因为我试图使用带有浮点数的/。

我使用bc for Windows修正了此问题。因为现在命令行中默认支持基本的浮点运算。

那是什么:

if %sex%==M set /a result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)

现在是:

set bc=bc\bc.exe
if /I "%sex%"=="M" echo 66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%) | %bc% & echo is the caloric intake required per-day for %name%