1

サードパーティ プログラムが問題を解決している間にバグを回避するために、送信されたバッチ ファイルを理解しようとしています。基本的に、文字列が一致するかどうかを判断するために、findstr 正規表現コマンドを実行しています。含まれている場合は、元のコマンドライン プログラムに渡す前に、取り除くべきではない特殊文字を手動で追加し直しています。

私が知る限り、提供されたものが機能しないか、理解できません。以下のコードの関連セクションを貼り付けます。

@echo off
setlocal
set username=%1
shift
echo %username% | findstr /r "^\"[0-9][0-9]*\"" >nul
if not errorlevel 1 (set username=";%username:~0,9%=%username:~10,4%?")
echo %username%

私が本当に疑問に思っている3つの部分は次のとおりです。

  1. 上記の正規表現のエスケープされていない解釈は、文字列が数字で始まり、一致が見つかるためにゼロ以上の追加の数字のみの文字で構成されている必要が^"[0-9][0-9]*"あることを意味すると思います。まあ、FINDSTR はエスケープされた引用符で奇妙なことをしているようで、私が試したものと一致させることはできません。周囲を削除すると機能しますが、入力文字列などの非数値文字を適切に拒否しません(そのサンプル文字列にはゼロの代わりに文字 O があります)。\"[0-9][0-9]*123456789O1234
  2. のポイントは何ですか>nul
  3. エラーレベル 2 を返す可能性があるため、 「エラーレベル 1 ではない」ではなく、エラーレベルが 0 であることを確認する方がよいのではないでしょうか?

とにかく、次のコードは機能しますが、私が望むほど正確ではありません。正規表現文字列の引用符が機能しない理由を理解しようとしています。おそらくこれはFINDSTRの制限ですが、まだ決定的なものに出くわしていません.

@echo off
setlocal
set username=%1
shift
echo %username% | findstr /r "^[0-9][0-9]*" >nul
if not errorlevel 1 (set username=";%username:~0,9%=%username:~10,4%?")
echo %username%

私の状況では文字数が 14 回であるため、クラスを 14 回繰り返すことで問題を回避できます ( 15 個を超えるクラスではクラッシュが発生します- 一番下までスクロールします)。これをより簡単に達成する方法、そしてもちろん残りの 2 つの質問については、まだ興味があります。

編集/作業ソリューション

@echo off
setlocal enableDelayedExpansion
set username=%~1
shift
echo !username!|findstr /r /c:"^[0-9][0-9]*$" >nul 
if not errorlevel 1 (set username=";!username:~0,9!=!username:~10,4!?")
echo !username!

ノート:

  • 既存のコードを dbenham のコードによく似たものに変更した後に最初に実行したとき、enableDelayedExpansionは、ユーザー名の設定に関する引用符と同様にエラーを出しました (以下を参照)。私が間違ったことを再現することはできませんが、現在はすべて機能しています (これは、他の誰かが同じ問題に遭遇した場合のためです)。
  • EOL マーカー (数値コンテンツのみを強制的に一致させるための鍵) を試してみました$が、他の問題が邪魔になっていて、それが解決策ではないと思いました。また、$作品が dbenham の回答のこの部分を見逃さないようにするには、「...エコーされた値とパイプ記号の間にスペースがないことも確認する必要があります。」
  • 要するに、 findstr の正規表現内に二重引用符を入れようとすると、構文が間違っている/機能しない/などのようです...解析している文字列/ファイルで実際に " と一致させようとしている場合を除きます。dbenhamの回答を参照してください彼が指摘したように、 %~1 を使用して、正規表現に追加する代わりに引数から引用符を取り除くことができます (必要に応じてプログラムで追加し直します)。

エラーメッセージ

C:>sample.bat 123456789
'enableDelayedExpansion' is not recognized as an internal or external command,
operable program or batch file.
'"' is not recognized as an internal or external command,
operable program or batch file.
!username!

参照リンク:

4

1 に答える 1

4

逆の順序で質問に答えます。

3)if not errorlevel 1おそらく、if %errorlevel%==0IF ERRORLEVEL 1はERRORLEVELが1以上の場合を意味するためと同じです。したがって、NOTを前に置くと、ERRORLEVELが1未満の場合を意味します。FINDSTRが負のERRORLEVELを返すことはないと思うので、構文は次のようになります。わかった。

2)>nulFINDSTRのstdout出力をnulデバイスにリダイレクトします。つまり、出力が無効になります。通常、一致する行が印刷されます。リターンコードにのみ関心があります。出力は表示されません。

1)元の正規表現は、引用符で始まり、少なくとも1桁の数字が続き、その後に別の引用符が続くすべての入力文字列と一致します。2番目の引用符の後に表示される可能性のある文字はすべて無視されます。

したがって、次の文字列(引用符を含む)は一致します。

  • 「0」
  • 「01234」
  • 「0」a
  • 「01234」a

次の文字列は一致しません。

  • 0
  • 01234
  • ""
  • 「0a」

一致する文字列の桁数が特定の長さに達すると、元のコードに問題が発生します。これは、終了引用符が削除されて終了引用符が引用され、スクリプトの残りの部分が失敗するためです。

要件がわからないため、コードを修正する方法がわかりません。

数字以外の文字列を照合したくないようです。つまり、正規表現の最後に行末マーカー$を含める必要があります。ただし、エコーされた値とパイプシンボルの間にスペースがないことも確認する必要があります。

おそらく、値に引用符を含めたくないと思います(そうでない場合は、最後にプログラムで引用符を追加する必要があります)。%〜1を使用して、指定された引数から囲んでいる引用符を取り除くことができます。

引数1が数字のみで構成されているかどうかを確認する場合は、次を使用できます。

setlocal enableDelayedExpansion
set "username=%~1"
echo !username!|findstr /r "^[0-9][0-9]*$" >nul

%1に含まれる文字を制御できないため、および&や|などの特殊文字が含まれている場合は、遅延展開を使用しました。通常の拡張を使用すると問題が発生します。私が与えた構文は防弾ではありませんが、ほとんどの「通常の」状況を処理します。

あなたの場合は必要ありませんが、検索文字列にスペースが含まれている場合に備えて、/cオプションを使用することをお勧めします。したがって、上記は次のように書くことができます

echo !username!|findstr /r /c:"^[0-9][0-9]*$" >nul

元のコードと変更されたコードの両方が、正規表現と一致しない場合にユーザー名を単純に渡すのは奇妙に思えます。多分それはあなたの意図です、多分そうではありません。

于 2012-05-17T03:56:54.007 に答える