Unixでは、私は走ることができmyscript '"test"'
、私は得るでしょう"test"
。
Windowsではcmd
、私が得ます'test'
。
二重引用符をパラメーターとして渡すにはどうすればよいですか?cmd
ウィンドウから手動でこれを行う方法を知りたいので、プログラムをテストするためにプログラムを作成する必要はありません。
Unixでは、私は走ることができmyscript '"test"'
、私は得るでしょう"test"
。
Windowsではcmd
、私が得ます'test'
。
二重引用符をパラメーターとして渡すにはどうすればよいですか?cmd
ウィンドウから手動でこれを行う方法を知りたいので、プログラムをテストするためにプログラムを作成する必要はありません。
回答:
症状をすぐに再現できません。ちょうど、またはさえ含むmyscript '"test"'
バッチファイルmyscript.bat
を試すと、すべての引用符が表示されます。@echo.%1
@echo.%~1
'"test"'
おそらく、次の^
ようなエスケープ文字を試すことができmyscript '^"test^"'
ます。
wscript
!Windowsにお任せください:)
cmd
。
引用符をエスケープする別の方法(おそらく好ましくない)は、特定の場所で使用されていることがわかりましたが、複数の二重引用符を使用することです。他の人のコードを読みやすくするために説明します。
基本的なルールは次のとおりです。
program param1 param2 param 3
4つのパラメータを渡しますprogram.exe
:param1
、param2
、param
、と3
。program one two "three and more"
する3つのパラメータを渡しますprogram.exe
:one
、two
、とthree and more
。hello"to the entire"world
。1つのパラメーターとして機能しますhelloto the entireworld
。"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ではありませんが、同じように動作すると思います)。
これを試して:
myscript """test"""
""は、パラメータで単一の "にエスケープします。
myscript """test test"""
、それは仕事(最初のパラメータは以下のように引き渡されていない"test
:Acutally、次の3つの引用符が必要です。myscript """"test test""
けれども、スキップすることができます最後に第三の引用を。
char **argv
、Cランチャーからspawn
やなどの関数を使用して別のプロセスに渡す必要があるときに役立ちましたexec
。ありがとうございました。:-)
ピーター・モーテンセンがコードスミスの答えについてのコメントで引用した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.txt
をfoo"a\"b "
に渡します。
foo "a\^"b " > out.txt
また、キャレット^
はエスケープ文字ではなく通常の文字である内側の状態で検出されるため、機能しません。そのため"a\^"b " > out.txt
、fooに渡されます。
(うまくいけば)常に機能する唯一の方法は、リダイレクトが機能するため、コマンドシェルを常に外部状態に保つことです。
リダイレクト(またはコマンドシェルに対して特別な意味を持つ他の文字)が必要ない場合は、キャレットなしで実行できます。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\"
myscript \"test\"