Windowsコマンドプロンプトで二重引用符のように単一引用符を処理する方法


6

私のシナリオは単純です-Mercurialオンラインブックからスクリプトサンプルをコピーし、Windowsコマンドプロンプトに貼り付けています。問題は、本のサンプルが一重引用符で囲まれた文字列を使用していることです。単一引用符で囲まれた文字列がWindowsコマンドプロンプトで渡されると、後者は単一引用符の間のすべてが1つの文字列に属していることを認識しません。

たとえば、次のコマンド:

hg commit -m 'Initial commit'

コマンドプロンプトであるようなぜなら後者扱い、貼り付けることができない'Initial commit'二つの文字列として- 'Initialcommit'。貼り付け後にコマンドを編集する必要があり、面倒です。

二重引用符と同様に単一引用符を処理するようにWindowsコマンドプロンプトに指示することは可能ですか?

編集

JdeBPからの返信に続いて、私は少し調査しました。概要は次のとおりです。

  • Mercurialエントリポイントは次のようになります(Pythonプログラムです)。

    def run():
        "run the command in sys.argv"
        sys.exit(dispatch(request(sys.argv[1:])))
    
  • そこで、mercurialで使用されるコマンドライン処理を模倣する小さなpythonプログラムを作成しました。

    import sys
    print sys.argv[1:]
    
  • Unixコンソールのログは次のとおりです。

    [hg@Quake ~]$ python 1.py  "1 2 3"
    ['1 2 3']
    [hg@Quake ~]$ python 1.py  '1 2 3'
    ['1 2 3']
    [hg@Quake ~]$ python 1.py  1 2 3
    ['1', '2', '3']
    [hg@Quake ~]$
    
  • 次に、それぞれのWindowsコンソールログを示します。

    C:\Work>python 1.py  "1 2 3"
    ['1 2 3']
    
    C:\Work>python 1.py  '1 2 3'
    ["'1", '2', "3'"]
    
    C:\Work>python 1.py  1 2 3
    ['1', '2', '3']
    
    C:\Work>
    

Windowsが一重引用符を二重引用符として扱わないことは明らかです。これが私の質問の本質です。


2
あなたは、エラーの「Windows」として、この質問をタグ付け、またはどちらかこれらは非常に多くありません DOSコマンドプロンプト
JdeBP

注-あなたのデモプログラムは、出力に一重引用符を追加しますが、これはおそらく物事を少しあいまいにします。実際には、Windows n unixは単一nの二重引用符を異なる方法で扱います。コマンドライン(プロンプトの後の領域)。1)GetCommandLine()2)argsv。argsvはおそらくGetCommandLineを実行することで機能し、メイン関数の最初の行に到達する前のプログラムは、これらのルール(Ms Visual Cの場合)またはそうでないルールに基づいて引数に分割します。msdn.microsoft.com/en-us/library/a1y7w461.aspx
barlop

このpastebin.com/raw.php?i=4Bq7unGd とこの pastebin.com/raw.php?i=QkhBJWGbの 両方をWindowsでコンパイルしてみてください。それらを引数で呼び出してみて、それらの出力から、引数を異なる方法で処理する方法を確認してください。GetCommandLine()を使用し、argsvを使用します。Windows自体は、引数を分離せず、argsvの要素を生成しません。
-barlop

回答:


6

引用文字は、command.comプロンプトでは変更できません。ただし、引用文字として単一引用符と二重引用符の両方を受け入れるPowerShellを使用できます。それらは、Unixシェルと同じように機能します。つまり、単一引用符は変数を展開しませんが、二重引用符は変数を展開します。

それでも、引用符内の引用符で問題が発生する可能性があります。たとえば、Windowsコンピューターにイチゴのperlがインストールされています。perl -e 'print time, "\n" 'PowerShellで実行すると、などの出力が表示され1321375663SCALAR(0x15731d4)ます。期待どおりに機能するには、二重引用符をエスケープする必要があります。perl -e 'print time, \"\n\" '


1

まず、コマンドプロンプトはコマンドインタープリターではありません。(コマンドプロンプトは、コマンドインタープリターによって表示されるものです。)次に、コマンドインタープリター、発行するプロンプト、およびWin32コンソールは、これとはまったく関係ありません

Win32プログラムでは、コマンドラインを「単語」に分割します。これは、CおよびC ++言語のプログラムに渡される引数配列として表示されるNULで終了するマルチバイト文字列ですmain()。UnicesとLinuxでは、オペレーティングシステムが実際に引数文字列配列の観点から機能するため、シェルは単語の分割を行います。これはWin32には当てはまりません。Win32では、オペレーティングシステム自体はコマンドテールの観点から動作しますコマンドテール:コマンドラインで最初に入力した引用符をすべて含む単一の長い文字列です。(あります ターゲットプログラムに渡される前にコマンドインタープリターによってこのコマンドテールに対して行われた処理の一部ですが、単語分割とは関係ありません。)

あなたの場合、hgプログラムのランタイムライブラリは次のコマンドテールで提供されています。

commit -m '初期コミット'

そのプログラムがコンパイルされた実行時ライブラリは、単一引用符が空白引用符であることを意味していることを知りません。それは慣習ではないからです。この規則は、二重引用符(および二重引用符の前のバックスラッシュ)のみを扱います。

この規則は、最初にプログラムを作成するために使用されるコンパイラーと共に提供されたランタイムライブラリに組み込まれています。規則を変更する場合は、この方法実行する個々のプログラムをすべて、単一引用符も認識する独自のランタイムライブラリと再リンクする必要があります。明らかにこれは非実用的です(ただし、これらがすべてCygwinプログラムでない限り)。

はるかに実用的なアプローチは、すでに行っていることを実行することです。WindowsはUnixではないことを認識し、使用する前にそれに応じて例を調整します。


1
あなたの答えの関連性を理解するのは難しいと思います。とにかく、質問を更新しました。
マーク

プログラムは一度にすべてを取得しますが、cmdインタープリター自体は二重引用符とは異なる方法で単一引用符を解釈しますが、それはすべてランタイムにかかっているわけではありません。たとえば、「&」を渡すと&がリテラルで、「&」がパラメータとして渡される場合、アンパサンド-&は特別なものとして扱われ、渡されないため、「&」とは異なります。また、cmd /?私は、ランタイムではなくcmdインタープリターであると思うルールの束を持っています。
-barlop

0

DOSがコマンドを解析する方法を編集できないと確信しています。基本プログラミングに固有のものです。

物事をスピードアップするために私が考えることができる唯一の解決策は、メモ帳ウィンドウを開いたままにし、「検索と置換」を実行することです-すべての単一引用符を二重引用符に置き換えます。そしてそこからDOSにコピー&ペーストします。


1
私は9Xのcommand.comについては知りません(DOSであると思います!9XはおそらくDOSのアドインです)が、NTのCMD.EXEはDOSではありません!DOSはオペレーティングシステムです。CMD.EXEはNTオペレーティングシステムのアドインであり、外部では実行されません。私はDOSと呼ぶために-1を与えました。NTのcmd.exe / 'windows command processor' "DOS"と呼ぶのは非常に素人的です。
-barlop
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.