1

我有一个奇怪的问题。下面的程序应该检查用户的输入并将其回显在屏幕上,除非输入是我在“if”语句中定义的某种“命令”,例如 /h 或 /r 或 /x。IF 语句会将字符串视为单个项目,而不是多个单独的字符串。因此,当我输入带有逗号(,)分号(;)等号(=)空格()制表符()引号(“)之类的分隔符时,它将搜索第二个项目,从而引发错误并退出。这就是我的问题。如果你不能理解我,请测试这个程序。我想在输入回显之前先检查那些“命令”。请赐教!:/谢谢。

@echo off

:again
set /p input= ^> 

if /i {%input%}=={/h} (
cls
echo /h
echo /r
echo /x
goto again
)

if /i {%input%}=={/r} (
cls
type blablafile.txt
goto again
)

if /i {%input%}=={/x} (
exit
)

echo %input%
goto again
4

2 回答 2

4

尝试将所有花括号更改为双引号。这解决了您在一些简单情况下提到的分隔符问题,例如输入字符串中的空格。例如,

if /i {%input%}=={/h}

可以改为

if /i "%input%"=="/h"

请注意,这不处理其他一些情况,例如输入字符串中的双引号。有关此问题的解决方案,请参阅其他答案。

于 2012-12-31T00:54:19.323 回答
3

IF 语句的一般形式为IF Value1 CompareOperator Value2 COMMAND

在实际执行 IF 之前,必须将该行解析为各种组件。有许多情况会导致语法无效。

一些明显的是特殊字符,如&, |, <, >: 这些必须像转义^&或引用一样"&"

<space>像, <tab>, ;, ,, 和之类的标记分隔符不是那么明显的问题=。这些也必须转义或引用。以您的程序中的一行<space>作为用户输入为例。`%input% 展开后,行看起来

if /i { }=={/h} (

解析器在第一个未转义/未引用的标记分隔符处终止 Value1,因此它认为 Value1 是{并且它认为它}是 CompareOperator 的一部分。这会产生语法错误。

另一个问题是带有奇数引号的值,例如您的用户输入示例".

if /i {"}=={/h} (

行情是一个状态机。启用引用后,解析器认为直到下一个引号之前的所有字符都是同一字符串的一部分。所以解析器认为 Value1 是{"}=={/h} (,并且命令不完整 - 另一个语法错误。

部分解决方案

你可以做类似的事情

if /i "%input%"=="/h" ...

它将与;or <space>, or=等​​输入一起使用。

但是仍然有很多输入会失败。例如:", "&"

完整的解决方案

进行测试的唯一可靠方法是启用延迟扩展并!input!使用%input%. 这是因为解析器在延迟扩展发生之前检测到 IF 语句的各个组成部分。

if /i !input!==/h (

解析器将 Value1 标识为!input!,然后在执行之前,将该值扩展为用户输入。此时不再需要进行解析——IF 语句“知道”整个扩展值是要比较的值。

这是您的代码的完整工作版本,其中包含延迟扩展修复:

@echo off
setlocal enableDelayedExpansion

:again
set /p input= ^>

if /i !input!==/h (
cls
echo /h
echo /r
echo /x
goto again
)

if /i !input!==/r (
cls
echo type blablafile.txt
goto again
)

if /i !input!==/x (
exit /b
)

echo !input!
于 2012-12-31T00:55:08.810 回答