2

この質問はもともと、指定された変数のパーセント記号のエスケープから来ています。あちらの良い答えを混乱させたくありません。しかし、私の問題は少し変わりました...

1 つ以上のパーセント記号を含む可能性がある二重引用符で囲まれた特定の文字列変数があると仮定しましょう。有効な遅延展開に永続的に切り替えることはできません (他のコードは既に使用可能です)。文字列変数をパラメータとして含む関数を呼び出す必要があります。これは私がこれまでに決定したものです:

@echo off & setlocal ENABLEEXTENSIONS
SET AlbumArtist=%1
CALL :EscapePoisonChars %AlbumArtist% AlbumArtist_VDN
echo %AlbumArtist_VDN%

CALL :EscapePoisonChars %%AlbumArtist%% AlbumArtist_VDN
echo %AlbumArtist_VDN%
endlocal &GOTO:EOF

:EscapePoisonChars
@echo off & setlocal ENABLEEXTENSIONS
SET TmpString="%~1"
SET TmpString=%TmpString:&=^^^&%
SET TmpString=%TmpString:(=^^^(%
SET TmpString=%TmpString:)=^^^)%
endlocal&SET %2=%TmpString:~1,-1%&GOTO :EOF

これはおそらく「クリーンなソリューション」ではないことを私は知っています。CALL :EscapePoisonChars %AlbumArtist% AlbumArtist_VDNしかし、ルーチンがパーセント記号によって呼び出されると消える理由を理解したいと思います。%%AlbumArtist%%二重のパーセント記号で囲まれた文字列変数で呼び出すと、必要な出力が得られます。

D:\Batch>PercentTwins.bat "100% Rock & Roll"
100 Rock & Roll
100% Rock & Roll

D:\Batch>

%AlbumArtist% が関数内または関数外で展開されると、結果が異なるのはなぜ:EscapePoisonCharsですか? エコーをオンにすると、パーセント記号がSET TmpString="~1". 説明があれば、cmd テクニックをさらに改善するのに役立ちます。ありがとう!

4

2 に答える 2

1

私が間違っていれば誰でも訂正してくれますが、あるコマンドの 1 つのパーセント記号が別のコマンドに渡されると、それらは消えると思います。同じコマンド内で使用されるだけの場合、通常は消えません。

(おそらくもっと「正しい」言い方があるか、この考えは完全に間違っているかもしれません)

( Microsoft サポート Web サイトのパーセント記号に関する情報)

于 2013-02-08T16:18:07.017 に答える
0

このcallコマンドは、%もう一度解析フェーズを開始します (質問投稿への受け入れられた回答を参照してください。 Windows コマンド インタープリター (CMD.EXE) はスクリプトをどのように解析しますか? )。これにより、%兆候が消えます。前もって符号を2 倍にすることもできますが、そのためには次のように遅延展開%を有効にする必要があります。

@echo off & setlocal ENABLEEXTENSIONS EnableDelayedExpansion
SET AlbumArtist=%1
set AlbumArtist=!AlbumArtist:%%=%%%%!
CALL :EscapePoisonChars %AlbumArtist% AlbumArtist_VDN
echo %AlbumArtist_VDN%
endlocal &GOTO:EOF

2 番目のサブルーチン呼び出しでは、2 つの解析フェーズ%で元の文字列の兆候が見られません。最初のフェーズは文字どおりに展開%%AlbumArtist%%し、2 番目のフェーズはそれを に展開します。%AlbumArtist%100% Rock & Roll

ただし、唯一の安全な構文に固執し、文字列を常に適切に引用符で囲むようにする
場合は、サブルーチンはまったく必要ありません。set

set "AlbumArtist=%~1"

%1指定された文字列を返します。%~1潜在的な周囲の引用符を削除します。割り当て式全体を引用符で囲むと、割り当てられた文字列自体の一部と見なされないため、有害な文字に対して構文が堅牢になります。""

文字列を使用/返す場合 (ここの例のように)、通常の (即時)展開echoを使用している場合は、安全性を維持するために文字列を引用符で囲む必要があります。%

set "AlbumArtist=%~1"
echo "%AlbumArtist%"

または、遅延展開により、引用符がなくても変数を安全に読み取ることができます。

set "AlbumArtist=%~1"
setlocal EnableDelayedExpansion
echo !AlbumArtist!
endlocal
于 2016-09-26T18:26:36.007 に答える