web-dev-qa-db-ja.com

Windowsバッチスクリプトで引用符を処理する

Windowsバッチファイルで、次の操作を行う場合:

set myvar="c:\my music & videos"

変数myvarは、引用符を含めて保存されます。正直なところ、私はその非常に愚かだと思います。引用符は、文字列の開始位置と終了位置を示すためのものであり、値自体の一部として保存されるものではありません。
これを防ぐにはどうすればよいですか?

ありがとう。

55
GetFree
set "myvar=c:\my music & videos"

引用符はmyvarの前にあることに注意してください。それは実際にはとても簡単です。サイドノート:&はコマンド区切り文字として読み込まれるため、引用符で囲まない限り、myvarは後でエコーできませんが、パスとしては機能します。

http://ss64.com/nt/set.html 「変数名にはスペースを含めることができます」

50
RuskoGuyachev

これが正しい方法です。

set "myvar=c:\my music & videos"

引用符は変数値に含まれません。

60
Craig Rorrer

変数の使用方法によって異なります。引用符なしで変数の値を使用するだけの場合は、遅延展開と文字列置換、またはforコマンドを使用できます。

@echo OFF
SETLOCAL enabledelayedexpansion

set myvar="C:\my music & videos"

Andynormancxが示すように、文字列には&が含まれるため、引用符が必要です。または、^を使用してエスケープすることもできますが、引用符は少し簡潔だと思います。

文字列置換で遅延展開を使用する場合、引用符なしで変数の値を取得します。

@echo !myvar:"=!
>>> C:\my music & videos

forコマンドも使用できます。

for /f "tokens=* delims=" %%P in (%myvar%) do (
    @echo %%P
)
>>> C:\my music & videos

ただし、コマンドで変数を使用する場合は、引用符で囲まれた値を使用するか、変数の値を引用符で囲む必要があります。

  1. 文字列置換と遅延拡張を使用して、引用符なしで変数の値を使用しますが、コマンドでは変数を使用します。

    @echo OFF
    SETLOCAL enabledelayedexpansion
    
    set myvar="C:\my music & videos"
    md %myvar%
    @echo !myvar:"=! created.
    
  2. forコマンドを使用して引用符なしで変数の値を使用しますが、コマンドで使用する場合は変数を引用符で囲む必要があります。

    @echo OFF
    set myvar="C:\my music & videos"
    
    for /f "tokens=* delims=" %%P in (%myvar%) do (
        md "%%P"
        @echo %%P created.
    )
    

端的に言えば、バッチファイルにスペースや&sが埋め込まれたパスまたはファイル名を使用する明確な方法はありません。

35
Patrick Cuff

Jscriptを使用します。

多くの月前(つまり、約8年の授与)、私は大規模なC++/VB6プロジェクトに取り組んでおり、ビルドの一部を実行するためのさまざまなバッチスクリプトがありました。

その後、誰かが Joel Test を指摘してくれたので、特にポイント2に夢中になり、小さなビルドスクリプトをすべて1つのビルドスクリプトに統合しようとしました。 。 。

そして、それは私の心をほぼ壊し、それらの小さなスクリプトをすべて異なるマシンで、わずかに異なるセットアップで一緒に動作させました。恐ろしいことに、特に変数とパラメータの受け渡しを設定しました。それは本当にもろくて、ほんの少しでもそれが壊れて、再び走るには30分の調整が必要です。

最終的に-私は頑固になります-私はたくさんのことをチャックしました約1日でJavaScriptですべてを書き直しました、CScriptでコマンドプロンプトから実行します。

私は振り返っていない。最近はMSBuildとCruise Controlですが、バッチスクリプトに少しでも関与する必要がある場合は、jscriptを使用します。

6
Binary Worrier

Windowsコマンドインタープリターを使用すると、setコマンド全体を引用符で囲むことができます(NT 4.0からWindows 2012 R2までのWindows NTのすべてのバージョンで有効)

スクリプトは次のように記述する必要があります。

@echo OFF

set "myvar=C:\my music & videos"

次に、必要に応じて変数を引用符で囲みます。

CMDプロンプトの操作は難解に思えるかもしれませんが、コマンドインタープリターは実際には内部ロジックに従って非常に堅実に動作するため、考え直す必要があります。

実際、setコマンドでは引用符を使用する必要はまったくありませんが、変数の割り当てを行う方法と引用符を使用しない方法の両方により、変数の周りに余分なスペースができますスクリプトのデバッグ時に注意してください。

例えば以下は両方とも技術的に有効ですが、末尾にスペースを入れることができるため、良い方法ではありません。

set myvar=some text   
set myvar="some text" 

例えば以下の両方は、Windowsコマンドインタープリターで変数を設定するのに適した方法ですが、二重引用符の方法が優れています。

set "myvar=Some text"
(set myvar=Some value)

これらの両方は、変数があなたが探しているデータを正確に持っているという解釈に何も残しません。

strong textただし、予約文字を使用しているため、目的のために引用符で囲まれたメソッドのみが有効に機能します

したがって、次を使用します。

set myvar="c:\my music & videos"

ただし、変数ISがこの文字列に正しく設定されていても、スティングをエコーすると、コマンドインタープリターはアンパーサンドをキーワードとして解釈し、別のステートメントが続くことを示します。

したがって、変数から文字列をエコーし​​たい場合は、CMDインタープリターにテキスト文字列であると伝える必要があるか、引用符を表示したくない場合は、次のいずれかを実行する必要があります。

wITH Quotes変数をエコーし​​ます。

Echo."%myvar%"

引用符なしで変数をエコーし​​ます。

Echo.%myvar:&=^&%
<nul SET /P="%myvar%"

上記の2つのシナリオでは、引用符なしで文字列をエコーできます。以下の出力例:

C:\Admin>    Echo.%myvar:&=^&%
C:\my music & videos

C:\Admin>    <nul SET /P="%myvar%"
C:\my music & videos
C:\Admin>
2
Ben Personick

設定するテキストになどの特定の文字が含まれる場合、mustが必要です。テキストにが含まれていない場合、引用符は不要です。

たとえば、テキストが「c:\ my music」だけの場合、次のようにできます。

set myvar = c:\my music

ただし、テキストにはがあるため、引用符が必要です。

編集:

または、デイブが彼の答えで言っているように、問題の文字を^^^でエスケープできますが、がエスケープする必要がある唯一の文字ではないので、そのアプローチに注意してください。実際には、問題のある文字をすべてエスケープするよりも、引用符を使用する方がはるかに簡単です。

1
andynormancx

エスケープ文字「^」を使用してみてください。

set myvar=c:\my music ^& videos

シェルは&をリテラルとして扱わない可能性があるため、myvarを展開するときは注意が必要です。上記が機能しない場合は、文字列にもキャレットを挿入してみてください。

set myvar=c:\my music ^^^& videos
1
Dave