2011-10-29 6 views
7

Windowsコマンドインタープリタで非常に奇妙な問題が発生しました。これはXPとWindows 7の両方で発生します。私の説明はPerlスクリプトにも当てはまりますが、この問題はコマンドラインでコマンドラインで任意の種類のプログラムを実行する場合に当てはまります。私が実行している場合このようにWindowsコマンドプロンプトで二重引用符をエスケープした副作用

use strict; 
use warnings; 
while (my $param = shift @ARGV) { 
    print "Param: [$param]\n"; 
} 

- - 私は単にそれをパラメータとして見たものを出力するPerlスクリプトcheck-params.plを使用していますテストのために

perl check-params.pl "a b|<>" c^|^<^>cc 

その後、出力は

[Param: a b|<>] 
[Param: c|<>cc] 
です

期待どおりです。特別な文字| <>は二重引用符でうまく動作しますが、引用符を外すと^でエスケープします。

二重引用符が

perl check-params.pl "a\" b|<>" 

に引用されたのparamなどに添加した場合しかし、その後、私はエラーを取得する -

> was unexpected at this time. 

しかし、二重引用符が後に特殊な文字を来る場合| <または>を入力しても問題ありません。

これを簡単に修正するには、特殊な| <>引用符で囲まれたパラメータの中に^を持つchar 例えば

perl check-params.pl "a\" b^|" 

しかしだけでなく、エスケープされた二重引用符は特殊文字には影響しません| <>現在のパラメータにありますが、後続のパラメータ内のこれらの特殊文字に影響します。

例えば、私はこれを行う場合 -

check-pipe.plは、単にパイプを受け取っ何を出力 -

use strict; 
use warnings; 
while (<STDIN>) { 
    print "PIPE RECEIVED ---> $_"; 
} 

perl check-params.pl "aa \"bb" ccc | perl check-pipe.pl 

を、出力がある -

Param: [aa "bb] 
Param: [ccc] 
Param: [|] 
Param: [perl] 
Param: [check-pipe.pl] 

すなわち、それパイプを扱う|リテラル文字として使用され、配管は行われません。

この問題の経験をお持ちの方もいらっしゃいましたが、回避策はありますか?

Webログファイルを処理するためのPerlスクリプトをいくつか書いてあり、コマンドラインで引用符付きのパラメータ内を渡すregexを使います。正規表現には、| <>と二重引用符も付いている可能性がありますので、上記のように問題が発生しています。

ご協力いただきありがとうございます。


返信ありがとうございますが、これをXP SP3で試してみると、Perlスクリプトには2つのコマンドラインパラメータが表示されています。 | \「は特殊な文字の後に来るので、

'c"' is not recognized as an internal or external command, 
operable program or batch file. 

しかし

echo "a b|\"c" 

作品 -

この問題は、Perlのに関連していない例えば

echo "a \"b|c" 

はエラーを生成します。

Itコマンドインタープリタのバグでなければなりません。私はこれについてもっと知り、可能であれば回避策を​​見つけることに興味があります。この問題は、いくつかの便利なスクリプトの実行を駄目にします。コマンドインタプリタにとっては非常に目立つ問題です。私はWindows 7でも試しましたが、上記のエコーテストでも同じ問題が発生します。


追加情報:

私はスクリプトがcheck-params.pl、より有用な情報を与えることをcheck-pipe.pl更新しました: -

check-params.plを: -

use strict; 
use warnings; 
while (my $param = shift @ARGV) { 
    print "COMMAND LINE RECEIVED: [$param]\n"; 
} 

check-pipe.pl: -

例えば、走行用

: -

perl pl/utils/check-params.pl l1 l1-b l1-c | perl pl/utils/check-pipe.pl l2 l2-b | perl pl/utils/check-pipe.pl l3 l3-b | perl pl/utils/check-pipe.pl united arsenal rangers raith 

は出力を生成します -

PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1] 
PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1-b] 
PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1-c] 
PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l2] 
PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l2-b] 
PIPE RECEIVED: COMMAND LINE RECEIVED: [l3] 
PIPE RECEIVED: COMMAND LINE RECEIVED: [l3-b] 
COMMAND LINE RECEIVED: [united] 
COMMAND LINE RECEIVED: [arsenal] 
COMMAND LINE RECEIVED: [rangers] 
COMMAND LINE RECEIVED: [raith] 

は、このように予想されるように、このコマンドラインは動作することを確認しました。スクリプトは、コマンドライン上の任意の数のパイプで動作します。


追加情報:

私は、これは、多くの回避策を使用して動作するように取得することができます見つける - 例えば^「ハリーは述べた一例であり、時にはあなたが使用しないように正規表現をrecraftすることができます。」と。特別なchar | <の前に2つの\ "シーケンスがある場合、問題は発生しません。コマンドを実行する前に、check-params.plとcheck-pipe.plを実行してPerlスクリプトにコマンドラインパラメータ例えば、私のOPへの上記の編集は、私のOPから修正したこれらのスクリプトを記述する。

+0

正規表現をインタラクティブに入力すると、あなたのスクリプトがあなたのためにプロンプ​​トを表示するのではなく、プロンプトを表示する方が便利な場合があります。コマンドライン。そうすれば、すべての特殊文字をエスケープする必要はありません。 –

+0

多くの情報に感謝します。私は自分のOPでのテストから印象を受けていました\ "エスケープシーケンスでした。私は非常に多くのコマンドを持っているので、コマンドラインパラメータを入力することは現実的ではありません。それらをテキストファイルから読み込み、いくつかをコピーして一度にすべて実行することもできます(クイック編集モードでは右クリックしてコマンドウィンドウに貼り付けることができます) –

答えて

2

二重引用符は最初の二重引用符と一致すると見なされ、

perl check-params.pl "a"" b|<>" 

あなたは(私のようにコマンドスクリプトを使用してテストしてみたperl.exeには、コマンドラインパラメータを解析する方法に応じて、期待している結果を生成する必要があります引用されたパラメータに二重引用符を含めるには、2つの二重引用符を使用します私はPerlをインストールしていない)。二重引用符として扱われる「」\の代わりに」ようにするには、スクリプトを変更する必要があります

追加:このコマンドラインc" is not recognizedを開始するエラーメッセージの

echo "a \"b|c" 

結果。これはバグではありません。

バックスラッシュはエスケープ文字ではありませんので、コマンドラインが残り(を作るパイプ(|)に続いて1つの引用符で囲まれた文字列("a \")が含まれてい)エコーコマンドからの出力がパイプされる追加のコマンド。

あなたの代わりに

echo "a ""b|c" 

を言うならば、ちょうど1引用符で囲まれた文字列("a ""b|c")があると、期待通りに動作します。

は残念ながら、私は今のActivePerlのコマンドライン構文解析は二つのパラメータに分割する

perl check-params.pl "a"" b|" 

を引き起こすことを確認することができます。 Perlでコマンドライン全体を取得し、それを自分で解析する必要があるかもしれません。

追加

perl check-params.pl ^"a\^" b^|c^" 

は、所望の結果を生成します。これは、引用符を含むすべての特殊文字をエスケープすることで機能します。

+0

^"は非常に役に立ち、これは私の多数の回避策にも当てはまります。ここでは2つの問題があるように見えます.1つはWindowsコマンドインタプリタの仕組み、もう1つはPerlのコマンドライン解析方法です。 –

関連する問題