パラメータの二重引用符をエスケープする


109

Unixでは、私は走ることができmyscript '"test"'、私は得るでしょう"test"

Windowsではcmd、私が得ます'test'

二重引用符をパラメーターとして渡すにはどうすればよいですか?cmdウィンドウから手動でこれを行う方法を知りたいので、プログラムをテストするためにプログラムを作成する必要はありません。


2
Windowsマシンに触れてから何年か経ちましたが、標準のエスケープ文字(バックスラッシュ\)は機能しませんか?例myscript \"test\"
Gazler、2011年

いいえ。\ test \を取得します。Windowsが/ではなく\を使用しているため、バックスラッシュをエスケープ機能として使用できないためだと思います。しかし、私は本当に知りません。
ブライアンフィールド、

使用しているWindowsのバージョンを確認しますが、\ "はWindows 7(Ultimate)で正常に動作します。ただし、複数の引用符を処理する方法があります(つまり、" ""が "または何かになる)が、私はできません。いつ、どのように機能するかを理解してください
Codesmith

回答:


22

症状をすぐに再現できません。ちょうど、またはさえ含むmyscript '"test"'バッチファイルmyscript.batを試すと、すべての引用符が表示されます。@echo.%1@echo.%~1'"test"'

おそらく、次の^ようなエスケープ文字を試すことができmyscript '^"test^"'ます。


3
次に、この質問への回答がさらに役立つかもしれませんか?
マウス、

2
ハ!それが間違いだとは思いもしませんでしたwscript!Windowsにお任せください:)
ブライアンフィールド、

4
実際^私のために動作しませんでしたが、\この回答ごとに、やった:stackoverflow.com/questions/2403647/...
kalenjordan

26
Windows:シェルの代わりに呼び出される実行可能ファイルによって、グロビング、シェル拡張、およびパラメーターのエスケープ解除が実行されるOS。呼び出された実行可能な名誉がある場合、どの規則があるかは決してわかりません。
binki 2014年

7
貴重な入力:blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/…。キャレットは確かにの選択のエスケープ文字ですcmd
ピーター-モニカを復活させる'05年

198

引用符をエスケープする別の方法(おそらく好ましくない)は、特定の場所で使用されていることがわかりましたが、複数の二重引用符使用することです。他の人のコードを読みやすくするために説明します。

基本的なルールは次のとおりです。

  1. 二重引用符で囲まれたグループに包まれていない場合は、スペースがパラメータを区切る:
    program param1 param2 param 34つのパラメータを渡しますprogram.exe
         param1param2param、と3
  2. :二重引用符で囲まれたグループは、値区切りプログラムにパラメータを渡すなどのスペースを無視
    program one two "three and more"する3つのパラメータを渡しますprogram.exe
         onetwo、とthree and more
  3. 次に、いくつかの混乱を説明します。
  4. 二重引用符で囲まれていないテキストに直接隣接する二重引用符で囲まれたグループは、1つのパラメーターに結合されます
    hello"to the entire"world。1つのパラメーターとして機能しますhelloto the entireworld
  5. 注:前のルールは、2つの二重引用符で囲まれたグループが互いに直接隣接して表示できることを意味していません。
  6. 閉じ引用符の直後の二重引用符は、二重引用符で囲まれたグループに隣接するプレーンなラップされていないテキストとして(またはその一部として)処理されますが、1つの二重引用符のみが1
    "Tim says, ""Hi!"""つのパラメーターとして機能します。Tim says, "Hi!"

したがって、3つの異なるタイプの二重引用符があります。開く引用符、閉じる引用符、およびプレーンテキストとして機能する引用符です。
最後に混乱するこの行の内訳は次のとおりです。

"二重引用符グループを開く
「」内のT
「」の中にいる私
"" s内のm
    「」の内側-スペースは分離しません
「」の内側
内部の「」
「」内のy
「」の内側
、「」の内側
    「」の内側-スペースは分離しません
"二重引用符で囲まれたグループを閉じる
"引用はすぐ後に続きます-ラップされていないテキストとして機能します:"
""の外側のH-前の隣接グループに参加します
""の外側-...
!「」の外側-...
"二重引用符グループを開く
"二重引用符グループを閉じる
"引用はすぐ後に続きます-ラップされていないテキストとして機能します:"

したがって、テキストは4つの文字グループに効果的に結合します(ただし、1つは何もありません)。
Tim says,  最初はスペースをエスケープするためにラップされ
"Hi!、2番目はラップされません(スペースはありません)
 。3番目は、何もラップされていない二重引用符グループです。
"4つ目は、ラップされていない引用です。

ご覧のように、次の二重引用符はプレーンテキストとして機能するのではなく、二重引用符で囲まれたグループを開きます。

このことから、引用符の内側と外側で、3つの二重引用符がプレーンテキストのエスケープされていない二重引用符として機能することを認識できるはずです。

「ティムは彼に言った、「最近何が起こっているのですか?」」

Tim said to him, "What's been happening lately?"期待どおりに印刷されます。したがって、3つの引用符は常にエスケープとして確実に使用できます。
ただし、理解すると、技術的に不要な空の二重引用符で囲まれたグループが追加されるため、末尾の4つの引用符を2つに減らすことができます。

これを閉じるいくつかの例を次に示します。

プログラムab REMが(a)と(b)を送信
プログラム "" "a" "" REMが送信( "a")
プログラム "" "a b" "" REMは( "a)および(b")を送信します
プログラム「」「こんにちは」「マイクは言った。」REMが送信します(「こんにちは」とマイクは言いました)。
プログラム "" a "" b "" c "" d "" REMは(abcd)を送信する
プログラム "hello to" "" quotes "" REM送信(hello to "quotes")
プログラム "" "" hello world "" REMが送信( "hello world")
プログラム "" hello "world" REMが送信( "hello world")
プログラム "" "hello" world "" REMは( "hello)と(world")を送信します
プログラム "hello" "world" "" REMが送信(hello "world")
プログラム "hello" "" world "" REMが送信(hello "world")

最後の注意:チュートリアルでこれを読んだことはありません-実験してすべてを思いつきました。したがって、私の説明は内部的には正しくないかもしれません。それにもかかわらず、上記の例はすべて与えられたとおりに評価されるため、私の理論が検証されます(ただし、証明されません)。

私はこれをWindows 7で64ビットでテストし、パラメーターを渡す* .exe呼び出しのみを使用しました(* .batではありませんが、同じように動作すると思います)。


11
+1。ただし、この動作はアプリケーションによって異なることに注意してください。Windowsでは、各アプリケーションが独自のコマンドラインパラメータを解析します。あなたが説明している動作は、Microsoftの標準Cライブラリの動作であると思います。これは、他のほとんどのWindows Cコンパイラでも複製されていると思います。
ハリージョンストン、

3
あなたの最後の行動の複数のエラー。プログラム "" "ab" ""->( "ab")、プログラム "hello to" "" quotes ""->(hello to "quotes)、プログラム" "" "hello world" "->(" Hello) (world)、プログラム "" "hello" world ""->( "hello)(world)、プログラム" "" hello "world" "->(" hello world)、プログラム "hello" "" world ""- >(hello "world)
Thomson

46
...私が言えることは、Windowsバッチファイルに問題があることです。これは、キリストのために引用をエスケープしています。それはある種のロケット科学である必要はありません。
James Ko

4
@JamesKoこれ以上は同意できませんでした。Windowsコマンドラインの不可解な不条理と矛盾は、私を怒らせることに決して失敗しません。誰がこのジャンクを設計しましたか?ああ、何年にもわたって時間を無駄にしました!Unixはとても簡単で、比較すると非常に理にかなっています。
カルロスA.イバラ


24

これを試して:

myscript """test"""

""は、パラメータで単一の "にエスケープします。


1
それはまったく正しくありません。試してみてくださいmyscript """test test"""、それは仕事(最初のパラメータは以下のように引き渡されていない"test:Acutally、次の3つの引用符が必要です。myscript """"test test""けれども、スキップすることができます最後に第三の引用を。
イグナイタ

ここですべての引用符を削除し、選択クエリフィルターで使用される文字列にパラメーター値を配置する必要がある場合はどうなりますか?誰かがお手伝いできますか?
SFDC_Learner 2015年

2
たぶんこの質問に気付かないかもしれませんがchar **argv、Cランチャーからspawnやなどの関数を使用して別のプロセスに渡す必要があるときに役立ちましたexec。ありがとうございました。:-)
virgo47

2

ピーター・モーテンセンがコードスミスの答えについてのコメントで引用した2番目の文書は、私にとって物事をより明確にしました。そのドキュメントはwindowsinspired.comによって書かれました。リンクの繰り返し:Windowsコマンドライン引数の引用とエスケープを理解するためのより良い方法

さらに試行錯誤すると、次のガイドラインが導かれます。

二重引用符"はすべてキャレットでエスケープします^。あなたが(例えば、Windowsコマンドシェルに特別な意味を持つ他の文字を使用する場合は<>|&)ではなく、通常の文字として解釈されるように、その後、あまりにも、キャレットでエスケープ。

プログラムfooでコマンドラインテキストを受け取り、"a\"b c" > dその出力をファイルout.txtにリダイレクトする場合は、Windowsコマンドシェルから次のようにプログラムを起動します。

foo ^"a\^"b c^" ^> d > out.txt

場合fooという解釈\"リテラルの二重引用符と意図した通りには空白を含める範囲を定めるの引数に二重引用符をエスケープを解除し、fooが一つの引数を指定すると、コマンドを解釈しa"b c、一つの引数>、および引数を一つd

代わりにfooが二重の二重引用符""をリテラルの二重引用符として解釈する場合、プログラムを次のように開始します

foo ^"a^"^"b c^" ^> d > out.txt

引用されたドキュメントからの重要な洞察は、Windowsコマンドシェルでは、エスケープされていない二重引用符が2つの可能な状態間の切り替えをトリガーするということです。

いくつかのさらなる試行錯誤は、初期状態では(ファイルまたはパイプへの)リダイレクトが認識され、キャレット^が二重引用符をエスケープし、キャレットが入力から削除されることを意味します。他の状態では、リダイレクトは認識されず、キャレットは二重引用符をエスケープせず、削除されません。これらの状態をそれぞれ「外側」と「内側」と呼びましょう。

コマンドの出力をリダイレクトする場合、リダイレクトに到達したときにコマンドシェルが外部状態になっている必要があるため、リダイレクトの前にエスケープされていない(キャレットによる)二重引用符が偶数個必要です。 foo "a\"b " > out.txt動作しません-コマンドシェルは、出力のみを渡してout.txtにリダイレクトするのではなく、結合されたコマンドライン引数として全体"a\"b " > out.txtfoo"a\"b "渡します。

foo "a\^"b " > out.txtまた、キャレット^はエスケープ文字ではなく通常の文字である内側の状態で検出されるため、機能しません。そのため"a\^"b " > out.txtfooに渡されます。

(うまくいけば)常に機能する唯一の方法は、リダイレクトが機能するため、コマンドシェルを常に外部状態に保つことです。

リダイレクト(またはコマンドシェルに対して特別な意味を持つ他の文字)が必要ない場合は、キャレットなしで実行できます。foo\"がリテラルの二重引用符として解釈される場合、次のように呼び出すことができます。

foo "a\"b c"

次に、foo"a\"b c"結合された引数テキストを受け取り、それをに等しい単一の引数として解釈できますa"b c

さて、ようやく元の質問へ。 myscript '"test"'Windowsコマンドシェルから呼び出され、myscriptに渡さ'"test"'ます。どうやらmyscriptは一重引用符と二重引用符を引数の区切り文字として解釈し、削除します。myscriptがリテラルの二重引用符として受け入れるものを理解し、それをコマンドで指定し^て、Windowsコマンドシェルにとって特別な意味を持つ文字をエスケープする必要があります。それmyscriptがUnixでも利用可能であることを考えると、おそらく\"トリックを行います。試す

myscript \^"test\^"

または、リダイレクトが必要ない場合は、

myscript \"test\"

ありがとうございました!cmdプロンプトテキストがcmdプロンプトテキストにエコーされた状態でvbscriptを実行しようとして、壁に頭をぶつけていました-これを継承しました-引用符をエスケープする方法を理解できませんでした。
PopeDarren

0

私はcmdからpowershellを呼び出しており、引用符を渡しても、ここでエスケープも機能しませんでした。重大なアクセントは、このWin 10サーフェスプロで二重引用符をエスケープするために機能しました。

>powershell.exe "echo la`"" >> test
>type test
la"

以下は、他の文字が二重引用符をエスケープするために取得した出力です。

la\
la^
la
la~

別の引用符を使用して引用符をエスケープすると、引用符がなくなりました。ご覧のとおり、文字自体は入力されていますが、二重引用符はエスケープされていません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.