バッチファイルでの変数の取り扱いについて(動的変数、静的変数の判定の違い)
解決済
回答 2
投稿
- 評価
- クリップ 1
- VIEW 3,236
前提・実現したいこと
バッチファイルに機能を追加しようと、色々仕様を確認していたのですが。
仕様?なのか挙動が不明な部分があり
変数の使い方が間違っているのだとは思うのですが…
仕様など教えて頂けませんでしょうか?
発生している問題・エラーメッセージ
!val!で比較した場合と%val%で比較した場合のIFの判定結果が違う
if !val! equ 2
"false"
if %val% equ 2
"true"
echo.!val!
2
echo.%val%
2
該当のソースコード
setlocal enabledelayedexpansion
for /f "tokens=3 delims= " %%i in ('find /V "" /C test.txt') do ( set val=%%i )
if !val! equ 2 (
echo "true"
)else (
echo "false"
)
if %val% equ 2 (
echo "true"
)else (
echo "false"
)
test.txt
aaa
bbb
試したこと
バッチファイルの文法を調べていた途中ですので、文法の確認程度です
補足情報(言語/FW/ツール等のバージョンなど)
Windows10での実行結果になります。
よろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+4
for
の中で参照しているのかと思ったそうでは無いので、これはYouheiSakuraiさんの回答とはちょっと違う原因です。
以下、空白の有無が問題になるので、見やすさのために空白を_
で表します。
原因は、変数val
にセットされているのが2
ではなく2_
なためです。
%val%
だと展開されてからif
の解釈がされますので、2
と2
が比較されます。
!val!
だとif
の構文解釈をしてから展開されます。つまり普通のプログラミング言語の変数参照と同じで、2_
と2
の比較になって、同じでは無いです。
対策としては、
for /f "tokens=3 delims= " %%i in ('find /V "" /C test.txt') do ( set val=%%i)
のように代入の右辺の%%i
の後ろの空白を取れば良いです。
なお、質問タイトルが「動的変数、静的変数」ですが、バッチスクリプトで動的変数というと、%DATE%
や%RANDOM%
のように、代入せずにシステムの与える値を参照する変数のことです。ざっくり言うと、参照するタイミングによって値の変わる参照専用の変数です(ざっくりのため若干不正確な説明です)。普通のプログラミング言語だと関数ですね。一方、set
で代入するのが静的変数です。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
以下の点が通常のプログラミング言語と違って、Windowsバッチで戸惑いを覚える部分です。
- 基本的に命令はそれ以下のパーセンテージ変数(%val%)が事前に全部評価された後に実行に移る
- でもそれだとIFやFORのブロック内に従属する命令で変数が扱えないので困る、そこで遅延評価の仕組みが必要になる
- ビックリマーク変数(!val!)は遅延評価される、つまりIFやFORのブロック内で従属の命令が実行される時に評価される
しかしながらif !val! equ 2
の!val!
は遅延評価の対象ではない(いかなる命令にも従属しないただの条件式の扱い)ので、!val!
という文字列と2
の比較になります。
一方でif %val% equ 2
はif 2 equ 2
と変数を評価した後に実行されます。
Windowsバッチはの仕様は本当に闇です。私の回答ももしかしたら間違いがあるかもしれないので、その点は悪しからずご了承ください。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/10/19 10:42
変数と=の間にスペースを含んではならないというのは確認していたのですが
まさか後ろのスペースもそのまま代入されてしまうとは…
ご提示のとおりの修正で、両方の判定が正しくtrueになるのを確認できました。
空白についてはうっかり入れてしまう事が多いので、かなり気を付けないといけないですね…
ありがとうございました。
2017/10/19 19:24