[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[原创] 批处理判断变量值是否为空的终极方法

  很多时候,我们需要检查某个变量的值是否为空,以便做后续处理。
  对于这个问题,很多人会毫不犹豫地选择 if "%str%"=="" …… 的句式,在早期的批处理中,还可以看到这样的语句:if [%str%]==[],有人把这两种写法称为“防空字符”。
  可是,这样做真的能在各种复杂的情况下判断某个变量的值是否为空吗?
  答案是否定的。
  先来看 if [%str%]==[],当%str%为空值的时候,它无疑能成功地捕获到这一情况,但是,如果%str%中含有特殊字符,比如>、&之类,这条语句就会报错。
  为了兼容这几个特殊字符,人们绞尽脑汁,想到了 if "%str%"=="" 语句,于是,>、&、|之类的特殊字符也能顺利通过验证了,这是防空字符的一大进步。
  但是,这条语句也不是完美的,因为有一个特殊字符它完全没办法处理!
  这个特殊字符是什么呢?
  它就是双引号"本身!
  我们执行一下如下代码:
  1. @echo off
  2. set str="
  3. if "%str%"=="" (echo yes) else echo no
  4. pause
复制代码
  CMD.EXE报错了:命令语法错误。
  原来,上面这条if语句执行的是 if """=="" ……,引号起到分组字符串的作用,而引号对是就近匹配的:第一个引号和第二个引号配成一对,第三个引号和第四个引号配成一对,第五个引号和第六个引号配成一对……,这条if语句最终的执行的是 if "==……,但是引号始终要作为分组字符来使用的,而单个的引号没有找到下一个可匹配的引号,所以就出现了语法错误。
  当把 %str% 的值改为两个引号的时候,上面这段代码的执行结果居然显示为no,想想这是为什么。
  if "%str%"==""……能兼容大部分特殊字符,但是偏偏不能兼容引号本身,那么,判断某个变量的值是否为空,是不是就没有更好的办法了呢?
  答案是肯定的,那就是:用 if defined str 语句来判断变量值是否为空。
  请执行以下代码:
  1. @echo off
  2. :Main
  3. cls
  4. set str=
  5. set /p "str=请输入任意字符,或直接回车:"
  6. if defined str (
  7.     echo 变量 str 的值不为空
  8. ) else echo 变量 str 为空值
  9. pause
  10. goto Main
复制代码
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

大家比较下以下两个代码,看看 defined 与 if "%input%" == "" 的区别:
  1. @echo off
  2. :input
  3. cls
  4. set /p input=直接回车返回,输入【Y】结束:
  5. if defined input echo 你将返回开始!&pause&goto input
  6. if /i "%input%"=="Y" echo Over&pause&exit
  7. echo 输入错误,请重试!
  8. pause&goto input
复制代码

  1. @echo off
  2. :input
  3. cls
  4. set /p input=直接回车返回,输入【Y】结束:
  5. if "%input%"=="" echo 你将返回开始!&pause&goto input
  6. if /i "%input%"=="Y" echo Over&pause&exit
  7. echo 输入错误,请重试!
  8. pause&goto input
复制代码

在功能上:
1、defined “如果已定义环境变量,DEFINED 条件的作用跟 EXISTS 的一样,除了它取得一个环境变量,返回的结果是 true。”
它只有 真 与 假 两种情况,因此,判断变量是否为空,当然最基本的办法就是 if not defined var (echo not) else echo yes
2、相比较之下,if "%input%"=="" 则对空格比较敏感些,它可以将空格独立出来处理。
在互动时输入任意字符进行判断,输入空格表示值不存在,这样更符合平时的使用习惯。
文本是否为空的判断也一样,一个文本中只有一堆空格而没有其他任何字符,我们通常认为这个文本是空的,而非defined认为的文本不为空。
综上,defined在比较苛刻的有与无的判断时使用,而 if "%input%"=="" 则在空格也是空值进行判断时使用。
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

回复  极品小猫


用 for:相比之下,for /f 更严谨通用
CrLf 发表于 2012-6-13 11:52



    额~我表达有问题, 其实是两段回复
正在烦恼特殊的字符的问题(不是变量名, 是变量值), 上面回复后面的那段话无视吧.
批处理输入的时候, 如果变量值含有 > >> | 诸如此类的如何预处理, 详细的看下面的帖子
http://bbs.bathome.net/viewthread.php?tid=17450

TOP

回复 9# 极品小猫


用 for:
  1. @echo off
  2. set "te st=测试1,只含空格或其他默认分隔符的情况"
  3. for %%a in ("te st") do if defined %%~a echo 存在变量 te st
  4. set "te* ?st=测试2,含 * 或 ? 的情况"
  5. for /f "eol== delims=" %%a in ("te* ?st") do if defined %%a echo 存在变量 te* ?st
  6. pause
复制代码
相比之下,for /f 更严谨通用

TOP

正烦恼特殊字符的问题, 如果变量名包含空格的事情实在蛋疼啊~谁愿意这样折腾?

TOP

  因为你的变量值中没有双引号,所以不会出错,请注意顶楼的全面描述,而不要以其中一种情况成立就否定顶楼的结论。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

不同意见-新手请教,请多批评

下面的程序是输入字符串,然后反向显示,并输出字符串个数。好像没有if "!var!"=="" 的问题啊。" % 都试过了
@echo off
setlocal enabledelayedexpansion

set  out=K
set /p a1=请输入字符串:
set  /a num=0

for /L %%i in (1,1,10000) do (
if "!a1!"=="" goto END
set  out=!out!^!a1:~-1!
set  a1=!a1:~0,-1!
set /a num=%%i
)

:END
IF /i  !num! == 0 (echo 字符串为空)  ELSE (echo !out:~1!字符串个数为 !num! )  
pause

[ 本帖最后由 tempwork1 于 2009-5-19 16:08 编辑 ]

TOP

专家到一个很高的水平了,都开始鸡蛋里挑骨头了,呵呵

TOP

原帖由 namejm 于 2009-4-6 22:57 发表
  嗯,变量名中含有空格的写法是极其BT的,.......

呵呵,所以我说是鸡蛋里挑骨头。。
技术问题请到论坛发帖求助!

TOP

  嗯,变量名中含有空格的写法是极其BT的,以前没怎么注意到,看来得花点时间折腾一下下。随风的研究结论,等本人测试过之后再决定是否补充到顶楼。

Re yslyxqysl:
  我一般不使用if "!var!"=="" 的做法,因为局限性太大了,详情我在顶楼也有描述。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

回复 2楼 的帖子

还不如用if "!var!"==""呢。

TOP

呵,鸡蛋里挑点骨头 ^_^
   用 if defined 判断某个变量是否被定义过时需注意以下2点:
   1、变量名若含空格,不能直接输入空格,有空格时需用变量来代替,且必须是用双!!来引用这个含空格的变量
      也就是必须开启延迟变量,或者将需判断的变量名赋值给 for 的 %%i 变量。
   2、若判断的变量名需要使用变量的字符截取功能时,则与上面的正好相反。
      即:不能使用!!来引用变量,即使是在for中也是一样。
http://www.bathome.net/viewthread.php?tid=2050&highlight=defined

[ 本帖最后由 随风 于 2009-4-6 22:33 编辑 ]
技术问题请到论坛发帖求助!

TOP

返回列表