web-dev-qa-db-ja.com

Windows FINDSTRコマンドの文書化されていない機能と制限は何ですか?

Windows FINDSTRコマンドは恐ろしく文書化されています。 FINDSTR /?またはHELP FINDSTRを介して利用できる非常に基本的なコマンドラインヘルプがありますが、それはひどく不十分です。 https://docs.Microsoft.com/en-us/windows-server/administration/windows-commands/findstr にオンラインでもう少しドキュメントがあります。

ドキュメントでは示唆されていない多くのFINDSTR機能と制限があります。また、事前の知識や慎重な実験なしでは予測できません。

質問は-文書化されていないFINDSTRの機能と制限は何ですか?

この質問の目的は、文書化されていない多くの機能のワンストップリポジトリを提供することです。

A)開発者は、そこにある機能を最大限に活用できます。

B)開発者は、本来あるべきように思えるのに、なぜ機能しないのか疑問に思って時間を無駄にしない。

応答する前に、既存のドキュメントを知っていることを確認してください。情報がヘルプでカバーされている場合、ここには属していません。

FINDSTRの興味深い使用法を示す場所でもありません。論理的な人がドキュメントに基づいてFINDSTRの特定の使用法の動作を予測できる場合、それはここに属しません。

同じ線に沿って、論理的な人が既存の回答に含まれる情報に基づいて特定の使用法の動作を予測できる場合、それもここには属しません。

179
dbenham

序文
この回答の多くの情報は、Vistaマシンで実行した実験に基づいて収集されています。特に明記しない限り、情報が他のWindowsバージョンに適用されるかどうかは確認していません。

FINDSTR出力
このドキュメントでは、FINDSTRの出力について説明することはありません。これは、一致する行が印刷されるという事実を暗示していますが、それ以上のものはありません。

一致する行出力の形式は次のとおりです。

filename:lineNumber:lineOffset:text

どこで

fileName: =一致する行を含むファイルの名前。要求が明示的に単一のファイルに対するものである場合、またはパイプ入力またはリダイレクト入力を検索する場合、ファイル名は出力されません。印刷するとき、fileNameには常に提供されたパス情報が含まれます。 /Sオプションを使用すると、追加のパス情報が追加されます。印刷されたパスは、常に指定されたパスに相対的であるか、何も指定されていない場合は現在のディレクトリに相対的です。

注- 非標準(およびドキュメント化が不十分な)ワイルドカード<および>を使用すると、複数のファイルを検索するときにファイル名の接頭辞を回避できます。これらのワイルドカードがどのように機能するかについての正確なルールは here にあります。最後に、これを見ることができます 非標準ワイルドカードがFINDSTRでどのように機能するかの例

lineNumber: = 10進値として表される一致する行の行番号。1は入力の最初の行を表します。 /Nオプションが指定されている場合にのみ出力されます。

lineOffset: =一致する行の先頭の10進バイトオフセット。0は1行目の1文字目を表します。 /Oオプションが指定されている場合にのみ出力されます。これは、not行内の一致のオフセットです。これは、ファイルの先頭から行の先頭までのバイト数です。

text = <CR>および/または<LF>を含む、一致する行のバイナリ表現。すべての行に一致するこの例が元のファイルの正確なバイナリコピーを生成するように、バイナリ出力には何も残されていません。

FINDSTR "^" FILE >FILE_COPY

ほとんどの制御文字と多くの拡張ASCII文字はXPでドットとして表示されます
XPの FINDSTRは、一致する行のほとんどの印刷不可能な制御文字を画面上にドット(ピリオド)として表示します。次の制御文字は例外です。 0x09タブ、0x0Aラインフィード、0x0B垂直タブ、0x0Cフォームフィード、0x0Dキャリッジリターンとして表示されます。

XP FINDSTRは、多くの拡張ASCII文字もドットに変換します。 ASCIIにドットとして表示される拡張XP文字は、コマンドラインで指定されたときに変換されるものと同じです。"コマンドラインパラメータの文字制限-拡張ASCII変換"セクションを参照してください。

出力がパイプされる、ファイルにリダイレクトされる、またはFOR IN()句内である場合、制御文字と拡張ASCIIはXPのドットに変換されません。

VistaおよびWindows 7では、すべての文字が常にドットとして表示され、決してドットとして表示されません。

リターンコード(ERRORLEVEL)

  • 0 (success)
    • 少なくとも1つのファイルの少なくとも1行で一致が見つかりました。
  • 1 (failure)
    • どのファイルのどの行にも一致するものは見つかりませんでした。
    • /A:xxオプションで指定された無効な色
  • 2 (error)
    • 互換性のないオプション/L/Rの両方が指定されました
    • /A:/F:/C:/D:、または/G:の後に引数がありません
    • /F:fileまたは/G:fileで指定されたファイルが見つかりません
  • 255(エラー)

検索するデータのソース(Windows 7のテストに基づいて更新)
Findstrは、次のいずれかのソースからのみデータを検索できます。

  • 引数として指定されたファイル名および/または/F:fileオプションを使用して。

  • リダイレクト経由の標準入力findstr "searchString" <file

  • パイプからのデータストリームtype file | findstr "searchString"

引数/オプションはリダイレクトより優先され、リダイレクトはパイプされたデータより優先されます。

ファイル名の引数と/F:fileは組み合わせることができます。複数のファイル名引数を使用できます。複数の/F:fileオプションが指定されている場合、最後のオプションのみが使用されます。ファイル名の引数にはワイルドカードを使用できますが、/F:fileが指すファイル内では使用できません。

検索文字列のソース(Windows 7のテストに基づいて更新されました)
/G:fileオプションと/C:stringオプションを組み合わせることができます。複数の/C:stringオプションを指定できます。複数の/G:fileオプションが指定されている場合、最後のオプションのみが使用されます。 /G:fileまたは/C:stringのいずれかが使用される場合、すべての非オプション引数は検索するファイルであると想定されます。 /G:file/C:stringも使用されていない場合、最初の非オプション引数は、スペースで区切られた検索語のリストとして扱われます。

/F:FILEオプションを使用する場合、ファイル内でファイル名を引用しないでください。
ファイル名にはスペースやその他の特殊文字を含めることができます。ほとんどのコマンドでは、そのようなファイル名を引用符で囲む必要があります。ただし、FINDSTR /F:files.txtオプションでは、files.txt内のファイル名を引用符で囲むことはできません。名前が引用されている場合、ファイルは見つかりません。

BUG-短い8.3ファイル名は/Dおよび/Sオプションを破壊する可能性があります
すべてのWindowsコマンドと同様に、FINDSTRは、検索するファイルを探すときに、ロングネームとショート8.3ネームの両方を一致させようとします。現在のフォルダーに次の空でないファイルが含まれていると仮定します。

b1.txt
b.txt2
c.txt

次のコマンドは、3つのファイルすべてを正常に検出します。

findstr /m "^" *.txt

b.txt2は、対応する短い名前B9F64~1.TXTが一致するため一致します。これは、他のすべてのWindowsコマンドの動作と一致しています。

ただし、/Dおよび/Sオプションのバグにより、次のコマンドはb1.txtのみを検出します

findstr /m /d:. "^" *.txt
findstr /m /s "^" *.txt

このバグにより、b.txt2が検出されず、同じディレクトリ内でb.txt2の後にソートされるすべてのファイル名が見つかりません。 a.txtなど、前にソートされた追加のファイルが見つかります。バグがトリガーされると、d.txtなどの後でソートする追加フ​​ァイルは失われます。

検索された各ディレクトリは独立して扱われます。たとえば、/Sオプションは、親のファイルの検索に失敗した後、子フォルダーでの検索を正常に開始しますが、バグにより短いファイル名が子で失われると、その子フォルダーの後続のすべてのファイルも検索されます逃した。

NTFS 8.3名の生成が無効になっているマシンで同じファイル名が作成された場合、コマンドはバグなしで機能します。もちろん、b.txt2は見つかりませんが、c.txtは適切に見つかります。

すべての短い名前がバグを引き起こすわけではありません。私が見たバグのある動作のすべての例には、8.3文字を必要としない通常の名前と同じ名前で始まる8.3文字の短い3文字を超える拡張子が含まれています。

このバグは、XP、Vista、およびWindows 7で確認されています。

印刷できない文字と/Pオプション
/Pオプションにより、FINDSTRは次の10進バイトコードのいずれかを含むファイルをスキップします。
0-7、14-25、27-31。

別の言い方をすれば、/Pオプションは、印刷できない制御文字を含むファイルのみをスキップします。制御文字は、31(0x1F)以下のコードです。 FINDSTRは、次の制御文字を印刷可能として扱います。

 8  0x08  backspace
 9  0x09  horizontal tab
10  0x0A  line feed
11  0x0B  vertical tab
12  0x0C  form feed
13  0x0D  carriage return
26  0x1A  substitute (end of text)

他のすべての制御文字は印刷不能として扱われ、その存在により/Pオプションはファイルをスキップします。

パイプ入力およびリダイレクト入力に<CR><LF>が追加される場合があります
入力がパイプされ、ストリームの最後の文字が<LF>でない場合、FINDSTRは自動的に<CR><LF>を入力に追加します。これはXP、Vista、およびWindows 7で確認されています。(以前はWindowsパイプが入力の変更を担当していると考えていましたが、FINDSTRが実際に変更を行っていることがわかりました。 )

Vistaのリダイレクトされた入力についても同じことが言えます。リダイレクトされた入力として使用されるファイルの最後の文字が<LF>でない場合、FINDSTRは自動的に<CR><LF>を入力に追加します。ただし、XPおよびWindows 7はリダイレクトされた入力を変更しません。

リダイレクトされた入力が<LF>で終了しない場合、[FINDSTRはXPおよびWindows 7でハングします
これはXPおよびWindows 7の厄介な「機能」です。リダイレクトされた入力として使用されるファイルの最後の文字が<LF>で終わらない場合、FINDSTRは終了時に無限にハングしますリダイレクトされたファイル。

パイプされたデータの最後の行は、単一の文字で構成されている場合は無視されます
入力がパイプされ、最後の行が<LF>が後に続かない単一の文字で構成される場合、FINDSTRは最後の行を完全に無視します。

例-単一の文字で<LF>のない最初のコマンドは一致しませんが、2文字の2番目のコマンドは正常に機能し、3番目のコマンドは改行で終わる1文字です。

> set /p "=x" <nul | findstr "^"

> set /p "=xx" <nul | findstr "^"
xx

> echo x| findstr "^"
x

DosTipsユーザーSponge Bellyが new findstr bug で報告しました。 XP、Windows 7、およびWindows 8で確認済み。Vistaについてはまだ聞いたことがない。 (テストするVistaはもうありません)。

オプション構文
オプションの前に/または-を付けることができます。オプションは、単一の/または-の後に連結できます。ただし、連結されたオプションリストには、OFFやF:などの複数文字オプションを最大1つ含めることができ、複数文字オプションはリストの最後のオプションでなければなりません。

以下は、「hello」と「goodbye」の両方を任意の順序で含む行の大文字と小文字を区別しない正規表現検索を表現する同等の方法です。

  • /i /r /c:"hello.*goodbye" /c:"goodbye.*hello"

  • -i -r -c:"hello.*goodbye" /c:"goodbye.*hello"

  • /irc:"hello.*goodbye" /c:"goodbye.*hello"

検索文字列の長さの制限
Vistaでは、単一の検索文字列の最大許容長は511バイトです。検索文字列が511を超える場合、結果はERRORLEVEL 2のFINDSTR: Search string too long.エラーになります。

正規表現検索を実行する場合、検索文字列の最大長は254です。255〜511の長さの正規表現は、ERRORLEVEL 2のFINDSTR: Out of memoryエラーになります。511を超える正規表現の長さは、FINDSTR: Search string too long.エラーになります。

Windows XPでは、検索文字列の長さは明らかに短くなっています。 Findstrエラー:「検索文字列が長すぎます」:「for」ループで部分文字列を抽出して一致させる方法 XP制限は、リテラル検索と正規表現検索の両方で127バイトです。

行の長さの制限
コマンドライン引数として、または/ F:FILEオプションを介して指定されたファイルには、既知の行の長さ制限がありません。単一の<LF>を含まない128MBファイルに対して検索が正常に実行されました。

パイプされたデータとリダイレクトされた入力は、1行あたり8191バイトに制限されています。この制限は、FINDSTRの「機能」です。パイプやリダイレクトに固有のものではありません。リダイレクトされたstdinまたはパイプ入力を使用するFINDSTRは、8kバイトを超える行には決して一致しません。 8k以上の行はstderrにエラーメッセージを生成しますが、少なくとも1つのファイルの少なくとも1行で検索文字列が見つかった場合、ERRORLEVELはまだ0です。

デフォルトの検索タイプ:リテラルと正規表現
/C:"string"-デフォルトは/ Lリテラルです。/Lオプションを/ C: "string"と明示的に組み合わせることは確かに機能しますが、冗長です。

"string argument"-デフォルトは、最初の検索文字列の内容に依存します。(<space>は検索文字列の区切りに使用されることに注意してください。)最初の検索文字列が、エスケープされていないメタ文字を少なくとも1つ含む有効な正規表現である場合、すべての検索文字列は正規表現として扱われます。それ以外の場合、すべての検索文字列はリテラルとして扱われます。たとえば、最初の文字列にはエスケープされていないドットが含まれているため、"51.4 200"は2つの正規表現として扱われますが、最初の文字列にはメタ文字が含まれないため、"200 51.4"は2つのリテラルとして扱われます。

/G:file-デフォルトは、ファイルの最初の空でない行の内容に依存します。最初の検索文字列が、エスケープされていないメタ文字を少なくとも1つ含む有効な正規表現である場合、すべての検索文字列は正規表現として扱われます。それ以外の場合、すべての検索文字列はリテラルとして扱われます。

推奨-/Lまたは/Rを使用する場合は、常に"string argument"リテラルオプションまたは/G:file正規表現オプションを明示的に指定します。

バグ-複数のリテラル検索文字列を指定すると、信頼できない結果が生じる可能性があります

次の簡単なFINDSTRの例では、一致するはずの一致が見つかりません。

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

このバグは、Windows Server 2003、Windows XP、Vista、およびWindows 7で確認されています。

実験に基づいて、次のすべての条件が満たされている場合、FINDSTRは失敗する可能性があります。

  • 検索は複数のリテラル検索文字列を使用しています
  • 検索文字列の長さが異なります
  • 短い検索文字列は、長い検索文字列とある程度重複しています
  • 検索では大文字と小文字が区別されます(/Iオプションなし)

私が見たすべての失敗で、失敗するのは常に短い検索文字列の1つです。

詳細については、 複数のリテラル検索文字列を使用したこのFINDSTRの例が一致を検出しない理由 を参照してください。

コマンドライン引数内の引用符とバックスラッシュ
Note-User MC NDのコメントは、このセクションの恐ろしく複雑なルールを反映しています。 。 3つの異なる解析フェーズが含まれます:

  • First cmd.exeでは、引用符を^ "としてエスケープする必要がある場合があります(FINDSTRとはまったく関係ありません)
  • Next FINDSTRは 2008 MS C/C++以前の引数パーサー を使用します。これには、 "および\の特別なルールがあります
  • 引数パーサーの終了後、FINDSTRはさらに、\の後に英数字をリテラルとして扱いますが、\の後に非英数字をエスケープ文字として扱います

この強調表示されたセクションの残りの部分は100%正確ではありません。多くの状況のガイドとして役立ちますが、完全に理解するには上記のルールが必要です。

コマンドライン検索文字列内での引用のエスケープ
コマンドライン検索文字列内の引用符は、\"のようなバックスラッシュでエスケープする必要があります。これは、リテラル検索文字列と正規表現検索文字列の両方に当てはまります。この情報は、XP、Vista、およびWindows 7で確認されています。

注:CMD.EXEパーサーの引用符もエスケープする必要がありますが、これはFINDSTRとは関係ありません。たとえば、一重引用符を検索するには、次を使用できます:

FINDSTR \^" file && echo found || echo not found

コマンドラインリテラル検索文字列内でバックスラッシュをエスケープする
リテラル検索文字列のバックスラッシュは通常、\または\\として表すことができます。通常、これらは同等です。(Vistaではバックスラッシュを常にエスケープしなければならない珍しいケースがあるかもしれませんが、テストするVistaマシンはもうありません)

ただし、いくつかの特殊なケースがあります。

連続するバックスラッシュを検索する場合、最後のmust以外はすべてエスケープされます。オプションで、最後のバックスラッシュをエスケープできます。

  • \\は、\\\または\\\\としてコーディングできます。
  • \\\は、\\\\\または\\\\\\としてコーディングできます。

引用の前に1つ以上のバックスラッシュを検索するのは奇妙です。ロジックは、引用符をエスケープする必要があることを示唆し、先頭の各バックスラッシュをエスケープする必要がありますが、これは機能しません!代わりに、先頭のバックスラッシュはそれぞれ二重にエスケープする必要があり、引用符は通常どおりエスケープされます。

  • \"\\\\\"としてコーディングする必要があります
  • \\"\\\\\\\\\"としてコーディングする必要があります

前述のように、1つ以上のエスケープされた引用符も、CMDパーサーの^でエスケープする必要がある場合があります

このセクションの情報は、XPおよびWindows 7で確認されています。

コマンドライン正規表現の検索文字列内でバックスラッシュをエスケープする

  • Vistaのみ:正規表現のバックスラッシュは、\\\\のように二重にエスケープするか、[\\]のような文字クラスセット内でシングルエスケープする必要があります。

  • XPおよびWindows 7:正規表現のバックスラッシュは、常に[\\]として表すことができます。通常、\\として表すことができます。しかし、バックスラッシュがエスケープされた引用符の前にある場合、これは機能しません。

    エスケープされた引用符の前の1つ以上のバックスラッシュは、二重エスケープするか、[\\]としてコーディングする必要があります

    • \"は、\\\\\"または[\\]\"としてコーディングできます。
    • \\"は、\\\\\\\\\"または[\\][\\]\"または\\[\\]\"としてコーディングできます。

/ G:FILEリテラル検索文字列内の引用符とバックスラッシュをエスケープする
/G:fileで指定されたリテラル検索文字列ファイル内のスタンドアロンの引用符とバックスラッシュはエスケープする必要はありませんが、エスケープすることはできます。

"\"は同等です。

\\\は同等です。

\\を見つけることが目的の場合は、少なくとも先頭のバックスラッシュをエスケープする必要があります。 \\\\\\\の両方が機能します。

\ "を見つけることが目的の場合は、少なくとも先頭のバックスラッシュをエスケープする必要があります。\\"\\\"の両方が機能します。

/ G:FILE正規表現検索文字列内の引用符とバックスラッシュをエスケープする
これは、ドキュメントに基づいてエスケープシーケンスが期待どおりに機能する1つのケースです。引用は正規表現のメタ文字ではないため、エスケープする必要はありません(ただし、可能です)。バックスラッシュは正規表現のメタ文字であるため、エスケープする必要があります。

コマンドラインパラメータの文字制限-拡張ASCII変換
ヌル文字(0x00)は、コマンドラインのどの文字列にも表示できません。その他のシングルバイト文字は、文字列に表示できます(0x01-0xFF)。ただし、FINDSTRは、コマンドラインパラメーター内で見つかった多くの拡張ASCII文字を他の文字に変換します。これは、2つの方法で大きな影響を及ぼします。

1)コマンドラインで検索文字列として使用される場合、多くの拡張ASCII文字は一致しません。この制限は、リテラル検索と正規表現検索で同じです。検索文字列に拡張ASCIIを含める必要がある場合は、代わりに/G:FILEオプションを使用する必要があります。

2)名前に拡張ASCII文字が含まれ、ファイル名がコマンドラインで指定されている場合、FINDSTRはファイルの検索に失敗する場合があります。検索するファイルの名前に拡張ASCIIが含まれている場合は、代わりに/F:FILEオプションを使用する必要があります。

FINDSTRがコマンドライン文字列に対して実行する拡張ASCII文字変換の完全なリストを次に示します。各文字は、10進数のバイトコード値として表されます。最初のコードはコマンドラインで指定された文字を表し、2番目のコードは変換後の文字を表します。注-このリストは、米国のマシンでコンパイルされました。他の言語がこのリストにどのような影響を与えるかはわかりません。

158 treated as 080     199 treated as 221     226 treated as 071
169 treated as 170     200 treated as 043     227 treated as 112
176 treated as 221     201 treated as 043     228 treated as 083
177 treated as 221     202 treated as 045     229 treated as 115
178 treated as 221     203 treated as 045     231 treated as 116
179 treated as 221     204 treated as 221     232 treated as 070
180 treated as 221     205 treated as 045     233 treated as 084
181 treated as 221     206 treated as 043     234 treated as 079
182 treated as 221     207 treated as 045     235 treated as 100
183 treated as 043     208 treated as 045     236 treated as 056
184 treated as 043     209 treated as 045     237 treated as 102
185 treated as 221     210 treated as 045     238 treated as 101
186 treated as 221     211 treated as 043     239 treated as 110
187 treated as 043     212 treated as 043     240 treated as 061
188 treated as 043     213 treated as 043     242 treated as 061
189 treated as 043     214 treated as 043     243 treated as 061
190 treated as 043     215 treated as 043     244 treated as 040
191 treated as 043     216 treated as 043     245 treated as 041
192 treated as 043     217 treated as 043     247 treated as 126
193 treated as 045     218 treated as 043     249 treated as 250
194 treated as 045     219 treated as 221     251 treated as 118
195 treated as 043     220 treated as 095     252 treated as 110
196 treated as 045     222 treated as 221     254 treated as 221
197 treated as 043     223 treated as 095
198 treated as 221     224 treated as 097

<CR>や<LF>を含む、上記のリストにない文字> 0はそれ自体として扱われます。 <CR><LF>などの奇妙な文字を含める最も簡単な方法は、それらを環境変数に入れて、コマンドライン引数内で遅延展開を使用することです。

/ G:FILEおよび/ F:FILEオプションで指定されたファイルで見つかった文字列の文字制限
nul(0x00)文字はファイルに表示できますが、C文字列ターミネーターのように機能します。 NUL文字の後の文字は、別の行にあるかのように異なる文字列として扱われます。

<CR>および<LF>文字は、文字列を終了する行終了記号として扱われ、文字列には含まれません。

他のすべてのシングルバイト文字は、文字列内に完全に含まれています。

Unicodeファイルの検索
FINDSTRは、nulバイトを検索できず、通常Unicodeには多くのnulバイト。

ただし、TYPEコマンドはBOM付きUTF-16LEを1バイト文字セットに変換するため、次のようなコマンドはBOM付きUTF-16LEで機能します。

type unicode.txt|findstr "search"

アクティブなコードページでサポートされていないUnicodeコードポイントは?文字に変換されます。

検索文字列にASCIIのみが含まれている限り、UTF-8を検索できます。ただし、マルチバイトUTF-8文字のコンソール出力は正しくありません。ただし、出力をファイルにリダイレクトすると、結果は正しくエンコードされたUTF-8になります。 UTF-8ファイルにBOMが含まれている場合、BOMは最初の行の一部と見なされ、行の先頭に一致する検索が実行されない可能性があることに注意してください。

UTF-8エンコードされた検索ファイル(BOMなし)に検索文字列を入れ、/ Gオプションを使用すると、マルチバイトUTF-8文字を検索できます。

行末
FINDSTRは、すべての<LF>の直後に行を分割します。 <CR>の有無は、改行には影響しません。

改行をまたいで検索
予想どおり、. regexメタキャラクターは<CR>または<LF>と一致しません。ただし、コマンドライン検索文字列を使用して改行を検索することは可能です。 <CR>と<LF>の両方の文字を明示的に一致させる必要があります。複数行の一致が見つかった場合、一致の最初の行のみが出力されます。 FINDSTRは、ソースの2行目に戻って検索を再開します。これは、一種の「先読み」タイプの機能です。

TEXT.TXTにこれらのコンテンツがあると仮定します(UnixまたはWindowsスタイルの可能性があります)

A
A
A
B
A
A

次に、このスクリプト

@echo off
setlocal
::Define LF variable containing a linefeed (0x0A)
set LF=^


::Above 2 blank lines are critical - do not remove

::Define CR variable containing a carriage return (0x0D)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

setlocal enableDelayedExpansion
::regex "!CR!*!LF!" will match both Unix and Windows style End-Of-Line
findstr /n /r /c:"A!CR!*!LF!A" TEST.TXT

これらの結果を与える

1:A
2:A
5:A

/ G:FILEオプションを使用した改行の検索は不正確です。これは、<CR>または<LF>に一致する唯一の方法がEOL文字を挟む正規表現文字クラス範囲式によるためです。

  • [<TAB>-<0x0B>]は<LF>に一致しますが、<TAB>および<0x0B>にも一致します

  • [<0x0C>-!]は<CR>に一致しますが、<0x0C>および!

    注-上記は正規表現バイトストリームの記号表現です。文字をグラフィカルに表現できないためです。

下のパート2で回答が続きました...

270
dbenham

上記のパート1からの回答 -30,000文字の回答制限に遭遇しました:

制限付き正規表現(regex)サポート
正規表現のFINDSTRサポートは非​​常に制限されています。ヘルプドキュメントにない場合、サポートされていません。

それを超えて、サポートされている正規表現は完全に非標準的な方法で実装されているため、grepやPerlなどの結果とは異なる結果になる可能性があります。

正規表現の行位置アンカー^および$
^は、入力ストリームの開始と<LF>の直後の任意の位置に一致します。 FINDSTRは<LF>の後の行も分割するため、単純な正規表現 "^"は、バイナリファイルを含むファイル内のすべての行に常に一致します。

$は、<CR>の直前の任意の位置に一致します。つまり、$を含む正規表現検索文字列は、Unixスタイルのテキストファイル内のどの行にも一致しません。また、<CR> <LF>のEOLマーカーがない場合、Windowsテキストファイルの最後の行にも一致しません。

注-前述のように、FINDSTRへのパイプされリダイレクトされた入力には、ソースにない<CR><LF>が追加される場合があります。明らかに、これは$を使用する正規表現検索に影響を与える可能性があります。

^の前または$の後の文字を含む検索文字列は、常に一致を検出できません。

位置指定オプション/ B/E/X
位置オプションは、リテラル検索文字列でも機能することを除いて、^および$と同じように機能します。

/ Bは、正規表現検索文字列の先頭の^と同じように機能します。

/ Eは、正規表現検索文字列の末尾の$と同じように機能します。

/ Xは、正規表現検索文字列の先頭に^があり、末尾に$があることと同じように機能します。

正規表現の単語の境界
\<は、正規表現の最初の用語でなければなりません。他の文字が先行する場合、正規表現は何にも一致しません。 \<は、入力の先頭、行の先頭(<LF>の直後の位置)、または「非単語」文字の直後の位置のいずれかに対応します。次の文字は「単語」文字である必要はありません。

\>は、正規表現の最後の用語でなければなりません。他の文字が後に続く場合、正規表現は何にも一致しません。 \>は、入力の終わり、<CR>の直前の位置、または「非単語」文字の直前の位置のいずれかに対応します。先行する文字は「単語」文字である必要はありません。

これは、10進バイトコードとして表される「非単語」文字の完全なリストです。 注-このリストは、米国のマシンでコンパイルされました。このリストに他の言語がどのような影響を与えるかはわかりません。

001   028   063   179   204   230
002   029   064   180   205   231
003   030   091   181   206   232
004   031   092   182   207   233
005   032   093   183   208   234
006   033   094   184   209   235
007   034   096   185   210   236
008   035   123   186   211   237
009   036   124   187   212   238
011   037   125   188   213   239
012   038   126   189   214   240
014   039   127   190   215   241
015   040   155   191   216   242
016   041   156   192   217   243
017   042   157   193   218   244
018   043   158   194   219   245
019   044   168   195   220   246
020   045   169   196   221   247
021   046   170   197   222   248
022   047   173   198   223   249
023   058   174   199   224   250
024   059   175   200   226   251
025   060   176   201   227   254
026   061   177   202   228   255
027   062   178   203   229

正規表現文字クラスの範囲[x-y]
文字クラスの範囲は期待どおりに機能しません。この質問を参照してください:---(なぜfindstrは大文字小文字を適切に処理しないのですか(状況によって)?
、およびこの回答: https://stackoverflow.com/a/8767815/101205

問題は、FINDSTRがバイトコード値で文字を照合しないことです(一般にASCIIコードと考えられますが、ASCIIは0x00-0x7Fでのみ定義されます)。ほとんどの正規表現の実装では、[A-Z]はすべて大文字の大文字として扱われます。ただし、FINDSTRは、SORTの動作にほぼ対応する照合シーケンスを使用します。 [A-Z]には、大文字と小文字(「a」を除く)の両方の完全な英語のアルファベット、および発音区別記号付きの英語以外のアルファベットが含まれます。

以下は、FINDSTRがサポートするすべての文字の完全なリストで、正規表現文字クラス範囲を確立するためにFINDSTRが使用する照合シーケンスでソートされています。文字は、10進バイトコード値として表されます。コードページ437を使用して文字を表示する場合、照合シーケンスが最も意味があると思います。注-このリストは、米国のマシンでコンパイルされました。このリストに他の言語がどのような影響を与えるかはわかりません。

001
002
003
004
005
006
007
008
014
015
016
017
018           
019
020
021
022
023
024
025
026
027
028
029
030
031
127
039
045
032
255
009
010
011
012
013
033
034
035
036
037
038
040
041
042
044
046
047
058
059
063
064
091
092
093
094
095
096
123
124
125
126
173
168
155
156
157
158
043
249
060
061
062
241
174
175
246
251
239
247
240
243
242
169
244
245
254
196
205
179
186
218
213
214
201
191
184
183
187
192
212
211
200
217
190
189
188
195
198
199
204
180
181
182
185
194
209
210
203
193
207
208
202
197
216
215
206
223
220
221
222
219
176
177
178
170
248
230
250
048
172
171
049
050
253
051
052
053
054
055
056
057
236
097
065
166
160
133
131
132
142
134
143
145
146
098
066
099
067
135
128
100
068
101
069
130
144
138
136
137
102
070
159
103
071
104
072
105
073
161
141
140
139
106
074
107
075
108
076
109
077
110
252
078
164
165
111
079
167
162
149
147
148
153
112
080
113
081
114
082
115
083
225
116
084
117
085
163
151
150
129
154
118
086
119
087
120
088
121
089
152
122
090
224
226
235
238
233
227
229
228
231
237
232
234

正規表現文字クラスの用語制限およびバグ
FINDSTRは、正規表現内で最大15文字のクラス用語に制限されているだけでなく、制限を超えようとする試みを適切に処理できません。 16以上の文字クラス用語を使用すると、対話型のWindowsポップアップ「文字列検索(QGREP)ユーティリティで問題が発生したため、閉じる必要があります。ご不便をおかけして申し訳ありません。」メッセージテキストは、Windowsのバージョンによって若干異なります。失敗するFINDSTRの例を次に示します。

echo 01234567890123456|findstr [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]

このバグはDosTipsユーザーJudago here によって報告されました。 XP、Vista、およびWindows 7で確認されています。

正規表現の検索にバイトコード0xFF(10進数255)が含まれている場合、失敗します(無期限にハングする可能性があります)
バイトコード0xFF(10進255)を含む正規表現検索は失敗します。バイトコード0xFFが直接含まれている場合、または文字クラス範囲内に暗黙的に含まれている場合は失敗します。 FINDSTR文字クラス範囲は、バイトコード値に基づいて文字を照合しないことに注意してください。文字<0xFF>は、<space>文字と<tab>文字の間の照合シーケンスの比較的早い段階で表示されます。したがって、<space><tab>の両方を含む文字クラス範囲は失敗します。

正確な動作は、Windowsのバージョンによってわずかに変わります。 0xFFが含まれている場合、Windows 7は無期限にハングします。 XPはハングしませんが、常に一致を検出できず、時折次のエラーメッセージを出力します- "プロセスは存在しないパイプに書き込もうとしました。"

Vistaマシンにアクセスできなくなったため、Vistaでテストすることができませんでした。

正規表現のバグ:.および[^anySet]はファイルの終わりに一致する可能性があります
正規表現.メタ文字は、<CR>または<LF>以外の任意の文字にのみ一致する必要があります。ファイルの最後の行が<CR>または<LF>で終了していない場合、ファイルの終わりに一致させるバグがあります。ただし、.は空のファイルと一致しません。

たとえば、<CR>または<LF>を終了せずに、xの単一行を含む「test.txt」という名前のファイルは、次と一致します。

findstr /r x......... test.txt

このバグは、XPおよびWin7で確認されています。

同じことが負の文字セットにも当てはまるようです。 [^abc]のようなものは、ファイルの終わりと一致します。 [abc]のような正の文字セットは正常に機能するようです。これはWin7でのみテストしました。

60
dbenham

大きな変数を検索するときに、findstrが予期せずハングすることがあります。

正確な条件や境界サイズを確認していません。 2GBを超えるファイルは危険にさらされる可能性があります。

私はこれについていろいろな経験をしましたので、単なるファイルサイズ以上のものです。これは リダイレクト入力がLFで終わらない場合、FINDSTRがXPおよびWindows 7でハングする のバリエーションのように見えますが、この特定の問題は、入力がnotリダイレクトされました。

次のコマンドラインセッション(Windows 7)は、3 GBファイルを検索するときにfindstrがハングする方法を示しています。

C:\Data\Temp\2014-04>echo 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890> T100B.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,10) do @type T100B.txt >> T1KB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1KB.txt >> T1MB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1MB.txt >> T1GB.txt

C:\Data\Temp\2014-04>echo find this line>> T1GB.txt

C:\Data\Temp\2014-04>copy T1GB.txt + T1GB.txt + T1GB.txt T3GB.txt
T1GB.txt
T1GB.txt
T1GB.txt
        1 file(s) copied.

C:\Data\Temp\2014-04>dir
 Volume in drive C has no label.
 Volume Serial Number is D2B2-FFDF

 Directory of C:\Data\Temp\2014-04

2014/04/08  04:28 PM    <DIR>          .
2014/04/08  04:28 PM    <DIR>          ..
2014/04/08  04:22 PM               102 T100B.txt
2014/04/08  04:28 PM     1 020 000 016 T1GB.txt
2014/04/08  04:23 PM             1 020 T1KB.txt
2014/04/08  04:23 PM         1 020 000 T1MB.txt
2014/04/08  04:29 PM     3 060 000 049 T3GB.txt
               5 File(s)  4 081 021 187 bytes
               2 Dir(s)  51 881 050 112 bytes free
C:\Data\Temp\2014-04>rem Findstr on the 1GB file does not hang

C:\Data\Temp\2014-04>findstr "this" T1GB.txt
find this line

C:\Data\Temp\2014-04>rem On the 3GB file, findstr hangs and must be aborted... even though it clearly reaches end of file

C:\Data\Temp\2014-04>findstr "this" T3GB.txt
find this line
find this line
find this line
^C
C:\Data\Temp\2014-04>

注、16進エディターですべての行がCRLFで終了していることを確認しました。唯一の例外は、 copyの動作 が原因で、ファイルが0x1Aで終了することです。ただし、この異常は「小さな」ファイルでは問題を引き起こしません

追加のテストにより、次のことを確認しました。

  • バイナリファイルに/bオプションでcopyを使用すると、0x1A文字が追加されなくなり、findstrが3GBファイルでハングしなくなります。
  • 3GBファイルを別の文字で終了すると、findstrもハングします。
  • 0x1A文字は、「小さな」ファイルでは問題を引き起こしません。 (他の終端文字についても同様です。)
  • 0x1Aの後にCRLFを追加すると、問題が解決します。 (LFだけで十分でしょう。)
  • typeを使用してファイルをfindstrにパイプすると、ハングすることなく機能します。 (これは、追加の行末を挿入するtypeまたは|の副作用による可能性があります。)
  • リダイレクトされた入力<を使用すると、findstrもハングします。 しかし、これは予想されています。 dbenhamの投稿 :で説明されているように、「リダイレクトされた入力はLFで終わる必要があります」
5
Disillusioned

複数のコマンドが括弧で囲まれ、ブロック全体にリダイレクトされたファイルがある場合:

< input.txt (
   command1
   command2
   . . .
) > output.txt

...その後、ブロック内のコマンドがアクティブである限り、ファイルは開いたままになります。そのため、コマンドはリダイレクトされたファイルのファイルポインターを移動できます。 MOREコマンドとFINDコマンドはどちらも、処理する前にStdinファイルポインターをファイルの先頭に移動するため、同じファイルがブロック内で数回処理される場合があります。たとえば、次のコード:

more < input.txt >  output.txt
more < input.txt >> output.txt

...これと同じ結果が生成されます。

< input.txt (
   more
   more
) > output.txt

このコード:

find    "search string" < input.txt > matchedLines.txt
find /V "search string" < input.txt > unmatchedLines.txt

...これと同じ結果が生成されます。

< input.txt (
   find    "search string" > matchedLines.txt
   find /V "search string" > unmatchedLines.txt
)

FINDSTRは異なります。 Stdinファイルポインターを現在の位置からnot移動しません。たとえば、次のコードは検索行の後に新しい行を挿入します。

call :ProcessFile < input.txt
goto :EOF

:ProcessFile
   rem Read the next line from Stdin and copy it
   set /P line=
   echo %line%
   rem Test if it is the search line
   if "%line%" neq "search line" goto ProcessFile
rem Insert the new line at this point
echo New line
rem And copy the rest of lines
findstr "^"
exit /B

この例 に示すように、リダイレクトされたファイルのファイルポインターを移動できる補助プログラムを使用して、この機能を有効に活用できます。

この動作は、最初に jeb at this post で報告されました。


2018-08-18を編集新しいFINDSTRバグが報告されました

FINDSTRコマンドには、このコマンドを使用して文字をカラーで表示し、そのようなコマンドの出力をCONデバイスにリダイレクトすると発生する奇妙なバグがあります。 FINDSTRコマンドを使用してテキストをカラーで表示する方法の詳細については、 このトピック を参照してください。

この形式のFINDSTRコマンドの出力がCONにリダイレクトされると、テキストが目的の色で出力された後に奇妙なことが起こります。より正確な説明は、テキストが黒い背景に黒いテキストとして出力します。 COLORコマンドを使用して画面全体の前景色と背景色をリセットすると、元のテキストが表示されます。ただし、テキストが「非表示」の場合、SET/Pコマンドを実行できるため、入力されたすべての文字が画面に表示されません。この動作は、パスワードの入力に使用される場合があります。

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"
5
Aacini

セクションに関するバグを報告したい検索するデータのソースen dash(–)またはem dash(—)ファイル名内。

より具体的には、最初のオプション-引数として指定されたファイル名を使用する場合、ファイルは見つかりません。オプション2-stdinリダイレクトまたは3-データパイプからのストリームを使用するとすぐに、findstrはファイルを検索します。

たとえば、次の簡単なバッチスクリプト:

echo off
chcp 1250 > nul
set INTEXTFILE1=filename with – dash.txt
set INTEXTFILE2=filename with — dash.txt

rem 3 way of findstr use with en dashed filename
echo.
echo Filename with en dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE1%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE1%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE1%" | findstr .
echo.
echo.
rem The same set of operations with em dashed filename
echo Filename with em dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE2%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE2%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE2%" | findstr .
echo.

pause

印刷されます:

ダッシュ付きのファイル名:

  1. 引数として
    FINDSTR:-dash.txtでファイル名を開けません

  2. リダイレクト経由の標準入力として
    私はダッシュ付きのファイルです。

  3. パイプからのデータストリームとして
    私はダッシュ付きのファイルです。

Emダッシュ付きのファイル名:

  1. 引数として
    FINDSTR:-dash.txtでファイル名を開けません

  2. リダイレクト経由の標準入力として
    私はemダッシュの付いたファイルです

  3. パイプからのデータストリームとして
    私はemダッシュの付いたファイルです

それが役に立てば幸い。

M.

2
matro