web-dev-qa-db-ja.com

引用符/文字列はPowershellでどのように機能しますか?

私は通常の古いWindowsコマンドシェルで動作するコマンドラインを持っていますが、どういうわけかPowershellで誤って解釈されます(私はPowershellにかなり慣れていません)。

sqlcmd -S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v DB="ksuite" -v OPTYPE="DB" -v BACKUPFOLDER="f:\SQLBackups" -v REPORTFOLDER="f:\SQLBackups\Reports" -v DBRETAINUNIT="days" -v DBRETAINVAL="7"

Powershellは、パスを必要とする引数からドライブ文字を削除しているようです。たとえば、Powershellで上記のコマンドを実行しようとすると、次のようになります。

Sqlcmd: ':\SQLBackups': Invalid argument. Enter '-?' for help.

ドライブ文字がないと無効であることを確認してください。二重引用、エスケープなどのバリエーションを試しましたが、機能しません。 Powershellの動作が異なることで何が欠けていますか?

3
Casey Wilkins

Jaykulの開始プロセスは、私もそれを行う方法です。 SQLCMDはcmd.exeを念頭に置いて設計されているため、引用符を表示したいということと、Powershellが引用符を使用する方法(またはそれ以上使用しない)との間に矛盾があります。

ストレートアップコールに使用できるものは次のとおりです。

sqlcmd -S .\SQLEXPRESS -i "`""f:\SQLBackups\ExpressMaint.sql`"" -v 'DB="ksuite"' -v 'OPTYPE="DB"' -v 'BACKUPFOLDER="`"'f:\SQLBackups'`"" -v 'REPORTFOLDER="`"'f:\SQLBackups\Reports'`"" -v 'DBRETAINUNIT="days"' -v 'DBRETAINVAL="7"'
0
squillman

手始めに、PowerShellは、すべてのパラメーターが単なる値、または-name valueペアであると想定しています。値の途中に引用符があると、奇妙なことが起こります...

このような場合は、パラメータ全体を引用する必要があります。

sqlcmd -S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v 'DB="ksuite"' -v 'OPTYPE="DB"' -v 'BACKUPFOLDER="f:\SQLBackups"' -v 'REPORTFOLDER="f:\SQLBackups\Reports"' -v 'DBRETAINUNIT="days"' -v 'DBRETAINVAL="7"'

ただし、私の通常の提案は、Start-Processを使用することです。これは、単一の文字列でall引数を取るため、次のことができます。

Start-Process sqlcmd @"
-S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v DB="ksuite" -v OPTYPE="DB" -v BACKUPFOLDER="f:\SQLBackups" -v REPORTFOLDER="f:\SQLBackups\Reports" -v DBRETAINUNIT="days" -v DBRETAINVAL="7"
"@ -RedirectStandardOutput f:\SQLBackups\CapturedOutput.log

最後の行の-RedirectStandardOutput f:\SQLBackups\CapturedOutput.logは、必要に応じてstdoutをファイルにキャプチャするだけです...エラー出力をログに記録する必要がある場合、または入力を提供する必要がある場合は、ファイルとの間でリダイレクトすることもできます。 。

3
Jaykul

私はsqlcmdを持っていないので、渡されているパラメーターをどのように解釈しているかについてコメントすることはできませんが、使用している構造を使用して、cmdシェルを呼び出したコマンドをエコーするだけのバッチファイルにパラメーターを配信します(echo %cmdcmdline%)は、パラメーターとして渡されるものが次のとおりであることを示しています。

cmd /c ""C:\Users\Joe\sqlcmd.cmd"  -S .\SQLEXPRESS -i f:\SQLBackups\ExpressMaint.sql -v DB=ksuite -v OPTYPE=DB -v BACKUPFOLDER=f:\SQLBackups -v REPORTFOLDER=f:\SQLBackups\Reports -v DBRETAINUNIT=days -v DBRETAINVAL=7"

Sqlcmdのパーサーは、Powershellがクエリの場所などの一部のパラメーターの引用符を削除する方法や、DB = "ksuite"パラメーターが大幅に変更される方法とはおそらく異なります。

動作する可能性のあるオプションの1つは、ロット全体を一重引用符で囲んで内部の二重引用符で囲まれた文字列を保持し、sqlcmdパーサーがこれを処理できることを期待することです。

sqlcmd '-S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v DB="ksuite" -v OPTYPE="DB" -v BACKUPFOLDER="f:\SQLBackups" -v REPORTFOLDER="f:\SQLBackups\Reports" -v DBRETAINUNIT="days" -v DBRETAINVAL="7"'

これにより、変更されていないパラメーターリストがsqlcmdに配信されますが、シェルに関する限り、単一のパラメーターとして配信されます。これが機能した場合は驚きます。次のように一重引用符で変更されているすべてのパラメーターブロックを選択的に引用すると、成功する可能性がはるかに高くなります。

sqlcmd.cmd -S .\SQLEXPRESS -i '"f:\SQLBackups\ExpressMaint.sql"' -v 'DB="ksuite"' -v 'OPTYPE="DB"' -v 'BACKUPFOLDER="f:\SQLBackups"' -v 'REPORTFOLDER="f:\SQLBackups\Reports"' -v 'DBRETAINUNIT="days"' -v 'DBRETAINVAL="7"'

それでも機能しない場合は、Powershell文字列解析でエスケープ文字として使用されるバッククォート文字を使用してシングルクォートとダブルクォートを切り替えるだけでなく、明示的にエスケープする必要がある他の項目がある可能性があります。

PowerShell内からhelp about_quotingを介して、引用とエスケープのすべての側面に関する詳細情報を取得できます。

1
Helvick