バッチファイルの変数から二重引用符を削除すると、CMD環境で問題が発生する


116

バッチ変数から引用符を削除する効果的で安全な方法を誰かが手助けできますか?

パラメータ%1、%2、%3などのリストを正常にインポートして名前付き変数に配置するバッチファイルを作成しました。これらのパラメータの一部には複数の単語が含まれているため、二重引用符で囲まれています。

> "Susie Jo" (%1)  
> "Smith Barnes" (%2)  
> "123 E. Main St." (%3)  

これらの%変数は、次に名前付き変数に配置されます。

> set FirstName=%1  
> set LastName=%2  
> set ShipAddr=%3  

変数の検証はエコーによって行われます。

echo。%FirstName%
echo。%LastName%
echo。%ShipAddr%

結果は次のように表示されます

"Susie Jo"  
"Smith Barnes"  
"123 E. Main St."  

選択した変数に含まれている引用符を削除する必要があります。たとえば、FirstNameとLastNameは他の場所で使用され、引用符を含めることはできません。

テストバッチファイルでは、変数に〜tilde文字を使用して引用符を削除することに成功しました。

> set FirstName=%~1
> set LastName=%~2 

解決策はあると思いましたが、すぐにバッチファイルの実行で異常な動作が発生しました。突然、CMDはロングパスステートメントを認識しなくなります。フルパスからのバッチファイルの通常の実行

> C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat

戻り値

> 'C:\Documents' is not recognized as an internal or external command....

したがって、着信%1%2 ...%n変数に〜tilde文字を追加すると、いくつかの変更が発生したように見えます。おそらくいくつかの環境変数が変更されていますか?

また、FORコマンドを使用してさまざまな試行を行い、変数内から引用符をクリアしてみました。それはぎこちないようで、タスクを実行する変数のリストを作成してこれを達成する方法を学ぶことができませんでした。

このようなもの:

for %%g in (%FirstName% %LastName%) do (
set %%g=%%~g
set %%h=%%~h
set FirstName=%%~g
set LastName=%%h
echo.%FirstName% %LastName%
)

私には2つの問題があると思います。

1)着信%1%2変数(%〜1など)に〜tildeを挿入するという私の「短くて甘い」アイデアは、一部の設定に影響を与え、CMDが長いパス名をナビゲートする方法を変更したようです。

2)選択した名前付き変数から引用符を削除するためのクリーンで簡単な方法を探しています。

より経験のある人のためのどんな助けでも最もありがたいです。私はここで私のスキルの終わりです...いくつかのガイダンスが必要です!

編集12/26/2009 13:36 PSTバッチファイル全体:

Blockquote
:: dataout.bat
::リビジョン12/25/2009 埋め込まれた「引用符」を削除するために、入力%variablesに〜tildeを追加します。
::コマンドラインパラメーターを使用してアドレスリストを
書き込みます:: QBooks IIFインポートのデータ出力リストを書き込みます
::書き込みRUIの販売注文データ
::テスト用のコマンドライン文字列のサンプル
:: listmail [firstname] [lastname] ["address string"] ["city string"] [state] [zip] [Order#] [PurchDate] [Regname] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Total] [ProductID] [Qty] [Price_Each] [PackPrep] [Shipping] [CommissionPmt] [Invoice#]
::例:dataout Bellewinkle Moose "123 Green Forest Way" "Vancouver" WA 98664 1004968 2009/05/25 "Bellewinkle Moose" "Olive Oyl" 101738 "On Account" 20.67 FK-1P 1 8.95 3.00 1.39 239
@echo off
cls
c:
cd \
cdドキュメントとsettings \ administrator \ myドキュメント\ txt \ batchtest
エコー処理%1%2
:VARISET
::%nコマンドラインパラメーターを文字列変数に変換します
($ FirstName)=%〜1
セット($ LastName)=%〜2
セット($ BillingAddress1)=%〜3
セット($ BillingCity)=%〜4
セット($ BillingState) =%〜5
セット($ BillingPostal)=%〜6
セット($ OrderNumber)=%〜7
セット($ Purch_Date)=%〜8
セット($ RegistrationName)=%〜9
シフト
セット($ TransactionID)=%〜9
シフト
セット($ PaymentMethod)=%〜9
シフト
セット($ Total)=%〜9
シフトセット($ ProductIdentifier)=%〜9
シフト
セット($ Quantity)=%〜9
シフト
セット($ Price_Each)=%〜9
シフト
セット($ Pack_Prep)=%〜9
シフト
セット($ Shipping)=%〜9
シフト
セット($ ServiceFee)=%〜9
シフト
セット($ Discount)=%〜9
シフト
セット($ Invoice)=%〜9
シフト
セット($
UnitPrice )=%〜9 セット_ShipCombName =%($ FirstName)%%($ LastName)%
echo ship combo name is%_ShipCombName%
pause
::文字列変数をログファイルに書き込む
echo FN%($ FirstName)%LN%($ LastName)%BA%($ BillingAddress1)%%($ BillingCity)%%($ BillingState)%%($ BillingPostal)%%($ OrderNumber)%%($ Purch_Date)%%($ RegistrationName)%%($ TransactionID)%%($ PaymentMethod)%%($ Total)%%($ ProductIdentifier)%%($ Quantity)%%($ Price_Each) %%($ Pack_Prep)%%($ Shipping)%%($ ServiceFee)%%($ Discount)%%($ Invoice)%%($ UnitPrice)%%_ShipCombName%>> d_out_log.txt
::アカウントの割り当てサービスプロバイダー
IF / i%($ PaymentMethod)%== Amazon Receivables SET _QBAcct = Amazon.com
:: 2009年12月25日、汎用性のための2番目のAmazon pm'tメソッドが追加されました
IF / i%($ PaymentMethod)%== Amazon SET _QBAcct = Amazon.com
IF / i%($ PaymentMethod)%== MAST SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== MasterCard SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== Visa SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== PayPal SET _QBAcct = PayPalPmts
IF / i%($ PaymentMethod)%==アカウント上SET _QBAcct =%($ RegistrationName)%
IF / i%($ PaymentMethod)%==メールSET _QBAcct =%($ RegistrationName)%
IF / i%( $ PaymentMethod)%== AMER SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== DISC SET _QBAcct = Auth / Net
:: QBAccount
IF / i%($ PaymentMethod)%==に基づいて担当者を割り当てるAmazon Receivables SET _Rep = Amazon
:: 2009年12月25日、汎用性のための2番目のAmazon pm'tメソッドを追加
IF / i%($ PaymentMethod)%== Amazon SET _Rep = Amazon
IF / i%($ PaymentMethod)%== MAST SET _Rep = BlueZap
IF / i%($ PaymentMethod)%== MasterCard SET _Rep = BlueZap
IF / i%($ PaymentMethod)%== Visa SET _Rep = BlueZap
IF / i%($ PaymentMethod)%== PayPal SET _Rep = BlueZap
IF / i%($ PaymentMethod)%==アカウント上SET _Rep = RB
IF / i%($ PaymentMethod)%==メールSET _Rep = RB
IF / i%($ PaymentMethod)%== AMER SET _Rep = BlueZap
IF / i %($ PaymentMethod)%== DISC SET _Rep = BlueZap
::重複するアドレスデータを確認します
findstr / i / s "%_ShipCombName%" addrlist.txt
echo errorlevel:%errorlevel%
if errorlevel 1 goto:ADDRWRITE
if errorlevel 0 goto: ADDRFOUND
:ADDRWRITE
echo%_ShipCombName%>> addrlist.txt
echo%($ BillingAddress1)%>> addrlist.txt
echo%($ BillingCity)%%($ BillingState)%%($ BillingPostal)%>> addrlist.txt
エコー。>> addrlist.txt
echoアドレスファイルの
書き込み:ADDRFOUND
echo selected rep is%_Rep%
echo selected account is:%_QBAcct%
pause
:: RUI OUT
:: write Merchant Order ID&RUI Order ID to RUI
:: check for duplicate RUI data in writeRUI.txt
cd ..
cd RegKOut
find / i "%($ OrderNumber)%" writeRUI.txt
echo errorlevel:%errorlevel%
if errorlevel 1 goto:RUIWRITE
if errorlevel 0 goto:IIFWRITE
:RUIWRITE
echo%($ Invoice)% %($ OrderNumber)%>> writeRUI.txt
::書き込みRUIの終了
:: IIF OUT
:IIFWRITE
:: writeIIF.txt で重複する請求書データを確認し
ますfind / i "%($ OrderNumber)%" writeIIF.txt
echo errorlevel:%errorlevel%
if errorlevel 1 goto:HEADWRITE
if errorlevel 0 goto:LINEWRITE
:HEADWRITE
:: write QB IIFインポートファイルへのヘッダー、出荷/処理、割引、担当者および手数料のデータ
echo%($ OrderNumber)%%($ Purch_Date)%Invoice%($ TransactionID)%%_QBAcct%Accounts Receivable%($ Total)%%_Rep %>> writeIIF.txt
echo H / P%($ Pack_Prep)%1?>> writeIIF.txt
echo SHP%($ Shipping)%1?>> writeIIF.txt
echo DISC%($ Discount)%1?>> writeIIF.txt
エコー通信%($ ServiceFee)%1?>> writeIIF.txt
:LINEWRITE
IF / i%($ ProductIdentifier)%equ PH-1 goto WRITE_DEFA ELSE goto WRITE_DISC
echo%($ ProductIdentifier)%
:WRITE_DISC
::カスタム変数から解析された割引価格を書き込みます:
echo%($ ProductIdentifier) %%($ Price_Each)%%($ Quantity)%?>> writeIIF.txt
goto:EOF
:WRITE_DEFA
:製品データから解析されたデフォルトの価格を書き込みます
echo%($ ProductIdentifier)%%($ UnitPrice)%%($ Quantity)%?>> writeIIF.txt
goto:EOF
:: 3秒の遅延
:: TYPE NUL | CHOICE.COM / N / CY / TY、3> NUL
:EOF


PowerShellを使用してこれを実行できますか?PowerShellを使用すれば、もう少し制御できるようになると思います。
ロバートハーベイ、

1
私はあなたのバッチファイルをチェックしました-それは正常に動作するようです( "shift set($ ProductIdentifier)=%〜9"という行を修正した後-これは、ここにコピーして貼り付けることのアーティファクトだと思います)。
atzz

ロバートハーベイありがとうございます。私はPowerShellを利用しています。私はプログラミングに関してはあまり経験がありません。学習曲線がどのようになるかわかりません。私がこれを選択した主な理由は、バッチファイルを使用した経験があります。バッチをコンパイルして、より速く実行するつもりです。ご返信ありがとうございます。
BobB 2009

ありがとうatzz:私はこのバッチファイルをもう少しテストしてきました。〜tildeとバニシングクォートは、長いパス名のあるCMD問題とは無関係であると合理的に確信しています。ルートの近くに短い名前のサブディレクトリを設定して長いパス名を排除することで、私はそれを回避しました。
BobB 2009

完全なバッチファイルを表示する必要はありません。質問を短くしてください。
JOR

回答:


192

最後に余分な二重引用符があります。これは、文字列の最後に二重引用符を追加します(文字列から両方の引用符を削除した後)。

入力:

set widget="a very useful item"
set widget
set widget=%widget:"=%
set widget

出力:

widget="a very useful item"
widget=a very useful item

注:二重引用符を単一引用符で置き換えるには、次のようにします。

set widget=%widget:"='%

注:「World」という語(大文字と小文字は区別されません)をBobBに置き換えるには、次のようにします。

set widget="Hello World!"
set widget=%widget:world=BobB%
set widget

出力:

widget="Hello BobB!"

最初の質問に関する限り(次のコードをバッチファイル.cmdまたは.batに保存して実行):

@ECHO OFF
ECHO %0
SET BathFileAndPath=%~0
ECHO %BathFileAndPath%
ECHO "%BathFileAndPath%"
ECHO %~0
ECHO %0
PAUSE

出力:

"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
Press any key to continue . . .

%0スクリプト名とパスです。
%1は、最初のコマンドライン引数です。


おかげで、これが私がSET BathFileAndPath=%~0SET BathFileAndPath=%~1
求めてい

なぜ%widget:"=%引用符を取り除くのか説明できますか?
CodyBugstein 14

4
@Imray- :old=new変数展開でのパターンマッチングと置換です。の"ようにold、何もないnew場合、引用符は、たとえそれらが不均衡であっても、途中にあっても削除されます。
ジェシーチザム

set widget =%widget: "=%は、ウィジェットが空白のときに奇妙な動作をし、" = "を返します
Rahul Misra

43

あなたの結論(1)は間違っているようです。何か他の要因が働いているに違いない。

バッチファイルパラメータの引用符の問題は、通常、引用符を削除して%~から適切な場所に手動で戻すことで解決されます。

例えば:

set cmd=%~1
set params=%~2 %~3

"%cmd%" %params%

周りの引用に注意してください%cmd%。それらがないと、スペースを含むパスは機能しません。

バッチコード全体を投稿できれば、より具体的な回答が得られるでしょう。


1
私は同意する; 私にはvar =%〜1のセットが問題なく機能するはずです。リクエストに応じてバッチファイル全体を投稿します。
BobB 2009

MSリファレンス:バッチパラメータの使用。修飾子がたくさんあることを誰が知っていましたか?参考までに、MSの公式ドキュメントには%~1as の説明が記載されていますExpands %1 and removes any surrounding quotation marks ("").
cod3monk3y 2014年

@ cod3monk3yまた、cmdこれらの修飾子について質問することもできcall /?ます。パラメーター修飾子のヘルプset /?、変数修飾子(おそらくあまり直感的でない)。かなり便利です。
atzz

12

私は通常、変数からすべての引用符を削除します:

set var=%var:"=%

そして、私がそれらを必要とするところはどこでも、それらを再び適用します。例えば:

echo "%var%"

私も最初はこれに問題があり、それを:として見ていました.-それを理解した後、問題なく動作しました。すばらしいヒントです。
DaveU 2014年

9

これを簡単な方法で実行するために多くの時間を費やしました。FORループを注意深く見た後、たった1行のコードでこれを実行できることに気付きました。

FOR /F "delims=" %%I IN (%Quoted%) DO SET Unquoted=%%I

例:

@ECHO OFF
SET Quoted="Test string"

FOR /F "delims=" %%I IN (%Quoted%) DO SET Unquoted=%%I

ECHO %Quoted%
ECHO %Unquoted%

出力:

"Test string"
Test string

このメソッドは、「SET Quoted = Test string」の間は関係ありません。次の質問は異なる」(二重引用符)が存在するかしないかをどのように関係するかもしれないためには、高度でお願いします。。
Rhak Kahr

3

これは、あるべきでない場所で%〜を使用している単純なバグのように聞こえます。%〜がバッチファイルの動作方法を根本的に変更しない場合の使用は、その単一の状況で文字列から引用符を削除するだけです。


3

私はこのリンクから学びました、もしあなたがXP以上を使っているなら、これは単にそれ自体で機能するでしょう:

SET params = %~1

ここで他のソリューションをWindows 7で動作させることはできませんでした。

それらを繰り返すために、私はこれをしました:

FOR %%A IN (%params%) DO (    
   ECHO %%A    
)

注:通常、スペースで区切られた引数を渡す場合にのみ、二重引用符が取得されます。


0
  1. 設定ウィジェット= "非常に便利なアイテム"
  2. ウィジェットを設定
  3. widget = "非常に便利なアイテム"
  4. set widget =%widget: "=%"
  5. ウィジェットを設定
  6. ウィジェットを設定=非常に便利なアイテム」

"4行目の末尾の引用は"、文字列に引用を追加しています。削除する必要があります。4行目の構文は次で終わります%


@ user195488-3行目が表示されていることwidget="a very useful item"確認し、 6行目が表示されていることwidget=a very useful item"確認します。7 set widget=%widget:"=%行目が表示され、widget=a very useful item 8 行目が表示された行の末尾に引用符がないことを確認します
ジェシーチザム

0

解決策はあると思いましたが、すぐにバッチファイルの実行で異常な動作が発生しました。突然、CMDはロングパスステートメントを認識しなくなります。フルパスからのバッチファイルの通常の実行

C:\ Documents and Settings \ Administrator \ My Documents \ Txt \ batchtest \ dataout.bat

戻り値

「C:\ Documents」は内部または外部コマンドとして認識されません...。

あなたの全体の問題があります。CMDはコマンドラインからのファイル名内のスペースを理解しないため、渡そうとしていると考えられます

およびSettings \ Administrator \ My Documents \ Txt \ batchtest \ dataout.bat

パラメータとして

「C:\ Documents」

プログラム。

パスにスペースを含むバッチファイルを実行するには、引用符で囲む必要があります。

> "C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat"

うまくいったでしょう。


0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

元のパラメーターに引用符があるかどうかに関係なく、引用符付きまたは引用符なしで示します。

また、引用符で囲まれている場合と含まれていない場合があるパラメータの存在をテストする場合は、上記のエコーの前に次の行を追加します。

'%1' == ''の場合、yoursubに移動します

しかし、引用符があるかどうかに関係なく、ファイルの存在をチェックする場合、それは次のとおりです。

存在する場合「!1!」goto othersub

一重引用符と二重引用符の使い方が異なることに注意してください。


0

すべての回答が完了しました。しかし、1つ追加したかったのですが、

FirstName =%〜1に設定

LastName =%〜2に設定

この行は機能するはずでしたが、小さな変更が必要でした。

「FirstName =%〜1」を設定します

「LastName =%〜2」を設定します

完全な割り当てを引用符で囲みます。問題なく引用を削除します。これは、引数の引用符の不要な問題を修正するための推奨される割り当て方法です。


0

単純なチルダ構文は、バッチファイルに渡されるコマンドラインパラメーターを囲む引用符を削除する場合にのみ機能します。

SET xyz=%~1

上記のバッチファイルコードは、最初と最後の引用符(存在する場合)を取り除く最初のパラメーターとして渡される値にxyzを設定します。

しかし、この単純なチルダ構文は、パラメーターとして渡されなかった他の変数では機能しません

他のすべての変数については、削除する先行文字と遅延文字を指定する必要がある拡張置換構文を使用する必要があります。実際には、最初の文字と最後の文字を、実際には何も表示せずに取り除くように指示しています。

@SET SomeFileName="Some Quoted file name"
@echo %SomeFileName% %SomeFileName:~1,-1%

削除する前に、最初と最後の文字が実際に引用されている文字を確認したい場合は、次のような追加のコードが必要になります

@SET VAR="Some Very Long Quoted String"
If aa%VAR:~0,1%%VAR:~-1%aa == aa""aa SET UNQUOTEDVAR=%VAR:~1,-1%
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.