1

奇妙な問題があります。以下のプログラムは、ユーザーの入力をチェックして画面にエコーすることになっています。ただし、入力が/ h、/ r、/xなどの「if」ステートメントで定義した「コマンド」のようなものでない限りです。IFステートメントは、文字列を複数の個別の文字列としてではなく、単一の項目として扱います。したがって、コンマ(、)セミコロン(;)等しい(=)スペース()タブ()引用( ")のような区切り文字で何かを入力すると、2番目の項目が検索され、エラーがスローされて終了します。これが私の問題です。理解できない場合は、このプログラムをテストしてください。入力がエコーされる前に、まずこれらの「コマンド」をチェックしたいと思います。教えてください!:/ありがとうございます。

@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>、ユーザー入力としてプログラムから1行を取得します。`%input%を展開すると、行は次のようになります。

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

パーサーは、最初のエスケープされていない/引用符で囲まれていないトークン区切り文字でValue1を終了するため、Value1はであると見なし、それはCompareOperator{}一部であると見なします。これにより、構文エラーが発生します。

もう1つの問題は、ユーザー入力の例のように、引用符の数が奇数の値です"

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

見積もりはステートマシンです。引用が有効になると、パーサーは次の引用までのすべての文字が同じ文字列の一部であると見なします。したがって、パーサーはValue1が{"}=={/h} (であると見なし、コマンドが不完全です-別の構文エラー。

部分的な解決策

あなたは次のようなことをすることができます

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

また、または;、、などの入力で機能します。<space>=

しかし、失敗する入力はまだたくさんあります。例:""&"

フルソリューション

テストを行う唯一の確実な方法は、遅延拡張を有効にして、の!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 に答える