200

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

ドキュメントでほのめかされていないFINDSTRの機能と制限がたくさんあります。また、事前の知識や注意深い実験がなければ、それらを予測することもできません。

したがって、問題は-文書化されていないFINDSTRの機能と制限は何ですか?

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

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

B)開発者は、何かが機能するはずなのに、なぜ機能しないのか疑問に思って時間を無駄にしません。

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

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

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

4

8 に答える 8

298

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

FINDSTR
の出力ドキュメントは、FINDSTRの出力をわざわざ説明することはありません。これは、一致する行が印刷されるという事実をほのめかしますが、それ以上のものはありません。

マッチングライン出力のフォーマットは次のとおりです。

filename:lineNumber:lineOffset:text

どこ

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

注-非標準の(および十分に文書化されていない)ワイルドカード <とを使用して複数のファイルを検索する場合は、ファイル名プレフィックスを回避できます>。これらのワイルドカードがどのように機能するかについての正確なルールは、ここにあります。最後に、非標準のワイルドカードがFINDSTRでどのように機能するかを示すこの例を見ることができます。

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

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

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

FINDSTR "^" FILE >FILE_COPY

/ Aオプションは、fileName:、lineNumber:、およびlineOffset:出力のみの色を設定します。一致する行のテキストは、常に現在のコンソールの色で出力されます。/ Aオプションは、出力がコンソールに直接表示される場合にのみ有効です。/ Aオプションは、出力がファイルにリダイレクトされるか、パイプされる場合は効果がありません。出力がCONにリダイレクトされたときのバグのある動作の説明については、Aaciniの回答の2018-08-18編集を参照してください。

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

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

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

VistaおよびWindows7は、常にすべての文字をドットとしてではなく、それ自体として表示します。

戻りコード(ERRORLEVEL)

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

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

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

  • リダイレクトによるstdinfindstr "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内のファイル名を引用符で囲まないようにする必要があります。名前が引用符で囲まれている場合、ファイルは見つかりません。

バグ-短い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ただし、 and/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、およびWindows7で確認されています。

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

言い換えると、この/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は、リダイレクトされた入力を変更しません。

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

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

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

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

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

> echo x| findstr "^"
x

DosTipsユーザーのSpongeBellyが新しいfindstrバグで報告しました。XP、Windows 7、およびWindows8で確認済み。Vistaについてはまだ聞いたことがありません。(テストするVistaはもうありません)。

オプションの構文
オプション文字は大文字と小文字を区別しないため/i/I同等です。

オプションの前にいずれかを付けるか/- オプションを単一/またはの後に連結することができます-。ただし、連結オプションリストには、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"

オプションも引用できます。したがって、、、/iおよび-i"/i"すべて"-i"同等です。同様に、、、および/c:stringはすべて同等です。"/c":string"/c:"string"/c:string"

/検索文字列がまたは-リテラルで始まる場合は、 /Cor/Gオプションを使用する必要があります。コメントでこれを報告してくれたStephanに感謝します(削除されたため)。

検索文字列の長さの制限
Vistaでは、単一の検索文字列に許可される最大長は511バイトです。検索文字列が511を超えるFINDSTR: Search string too long.と、ERRORLEVEL2のエラーが発生します。

正規表現検索を実行する場合、検索文字列の最大長は254です。255〜511の長さの正規表現ではFINDSTR: Out of memory、ERRORLEVEL2のエラーが発生します。正規表現の長さが>511の場合、FINDSTR: Search string too long.エラーが発生します。

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

行の長さの制限
コマンドライン引数として、または/ F:FILEオプションを介して指定されたファイルには、既知の行の長さの制限はありません。<LF>が1つも含まれていない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、およびWindows7で確認されています。

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

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

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

詳細については、「複数のリテラル検索文字列を使用したこのFINDSTRの例で一致が見つからないのはなぜですか? 」を参照してください。


コマンドライン引数内の引用符とバックスラース注-ユーザー MCNDのコメントは、このセクションの実際の恐ろしく複雑なルールを反映しています。関連する3つの異なる解析フェーズがあります。

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

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

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

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

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

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

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

連続する円記号を検索するときは、最後を除くすべてをエスケープする必要があります。最後の円記号はオプションでエスケープできます。

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

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

  • \"次のようにコーディングする必要があります\\\\\"
  • \\"次のようにコーディングする必要があります\\\\\\\\\"

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

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

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

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

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

    エスケープされた引用符の前の1つ以上の円記号は、二重エスケープするか、次のようにコーディングする必要があります。[\\]

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

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

"\"は同等です。

\\\は同等です。

\\を見つけることが目的の場合は、少なくとも先頭の円記号をエスケープする必要があります。\\\\\\\仕事の両方。

「」を見つけることが目的の場合は、少なくとも先頭の円記号をエスケープする必要があります。両方とも\\"機能し\\\"ます。

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

コマンドラインパラメータの文字制限-拡張ASCII変換
ヌル文字(0x00)は、コマンドラインのどの文字列にも表示できません。その他の1バイト文字は、文字列(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

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

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

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

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

Unicodeファイル
の検索FINDSTRはnulバイトを検索できず、Unicodeには通常多くのnulバイトが含まれているため、ほとんどのUnicode(UTF-16、UTF-16LE、UTF-16BE、UTF-32)を適切に検索できません。

ただし、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>の有無は、改行に影響を与えません。

改行を検索する
予想どおり、.正規表現のメタ文字は<CR>または<LF>と一致しません。ただし、コマンドライン検索文字列を使用して改行を検索することは可能です。<CR>文字と<LF>文字の両方を明示的に一致させる必要があります。複数行の一致が見つかった場合、一致の1行目のみが出力されます。次に、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に続きます...

于 2012-01-13T01:40:09.500 に答える
70

上記のパート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

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

問題は、FINDSTRがバイトコード値で文字を照合しないことです(通常はASCIIコードと考えられますが、ASCIIは0x00〜0x7Fでのみ定義されます)。ほとんどの正規表現の実装では、[AZ]はすべて大文字の英語の大文字として扱われます。ただし、FINDSTRは、SORTの動作にほぼ対応する照合シーケンスを使用します。したがって、[AZ]には、大文字と小文字の両方(「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以上の文字クラスの用語を使用すると、 「文字列の検索(QGREP)ユーティリティで問題が発生したため、閉じる必要があります。ご不便をおかけして申し訳ありません。」というインタラクティブなWindowsポップアップが表示されます。メッセージテキストは、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によってここで報告されました。XP、Vista、およびWindows7で確認されています。

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

正確な動作は、Windowsのバージョンによってわずかに異なります。0xFFが含まれている場合、Windows7は無期限にハングします。XPはハングしませんが、常に一致するものを見つけることができず、「プロセスが存在しないパイプに書き込もうとしました」というエラーメッセージが出力されることがあります。

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

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

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

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

このバグはXPとWin7で確認されています。

同じことが否定的な文字セットにも当てはまるようです。のようなもの[^abc]はEnd-Of-Fileと一致します。のようなポジティブな文字セットは[abc]うまく機能しているようです。私はこれをWin7でのみテストしました。

于 2013-11-23T06:03:30.337 に答える
8

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

< 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ファイルポインタを現在の位置から移動しません。たとえば、このコードは検索行の後に新しい行を挿入します。

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によって最初に報告されました。


編集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%"
于 2015-02-02T13:17:38.933 に答える
7

findstr大きなファイルを検索すると、予期せずハングすることがあります。

正確な条件や境界サイズは確認していません。2GBより大きいファイルは危険にさらされているのではないかと思います。

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

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

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。唯一の異常は、動作方法が原因でファイルが終了すること0x1Aです。ただし、この異常は「小さな」ファイルでは問題を引き起こさないことに注意してください。copy

追加のテストで、私は次のことを確認しました。

  • copyバイナリファイルの/bオプションを指定して使用すると、0x1A文字の追加が防止findstrされ、3GBファイルにハングアップしません。
  • 別の文字で3GBファイルを終了すると、もfindstrハングします。
  • この0x1A文字は、「小さな」ファイルでは問題を引き起こしません。(他の終了文字についても同様です。)
  • CRLF後に追加0x1Aすると問題が解決します。(LFそれ自体でおそらく十分でしょう。)
  • ハングせずtypeにファイルを作品にパイプするために使用します。findstr(これは、いずれかの副作用、または追加のEnd Of Lineを挿入する副作用が原因である可能性がありますtype|
  • リダイレクトされた入力を使用すると、ハングする<原因にもなります。しかし、これは予想されることです。dbenhamの投稿で説明されているように、「リダイレクトされた入力は「」で終わる必要があります。findstrLF
于 2014-04-08T16:34:56.863 に答える
2

ファイル名にenダッシュ(–)またはemダッシュ(—)を使用した場合に、最初の回答で検索するデータのソースのセクションに関するバグを報告したいと思います。

具体的には、最初のオプション(引数として指定されたファイル名)を使用しようとすると、ファイルが見つかりません。オプション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. リダイレクトを介したstdinとして
    、私はダッシュ付きのファイルです。

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

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

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

  2. リダイレクトを介したstdinとして
    、私はemダッシュ付きのファイルです。

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

それが役に立てば幸い。

M。

于 2015-03-22T11:36:55.703 に答える
2

無効または互換性のないスイッチがなく、検索文字列が該当する長さの制限を超えていない場合、findstrコマンドErrorLevel(または終了コード)を次のいずれかの値に設定します。

  • 0指定されたすべてのファイル全体で1行に少なくとも1つの一致が見つかった場合。
  • 1そうでなければ;

次の場合、行に一致が含まれていると見なされます。

  • オプションが指定されておらず/V、検索式が少なくとも1回発生します。
  • オプションが指定され、/V検索式は発生しません。

これは、/Vオプションが返されたを変更することを意味しますErrorLevelが、それは単にそれを元に戻すだけではありませ

たとえば、test.txt2行のファイルがあり、一方には文字列textが含まれているが、もう一方には含まれていない場合、両方とも。のfindstr "text" "test.txt"findstr /V "text" "test.txt"返します。ErrorLevel0

基本的に、次のように言うことができます。findstr少なくとも1行を返す場合は、に設定され、それ以外の場合ErrorLevelはに設定されます。01

この/Mオプションは値に影響を与えずErrorLevel、出力を変更するだけであることに注意してください。

(完全を期すために、findコマンド/Vはオプションに関してまったく同じように動作しますErrorLevel/Cオプションは影響しませんErrorLevel。)

于 2019-09-17T21:33:58.340 に答える
2

FINDSTRには、https: //superuser.com/questions/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-toで説明および解決した色のバグがあります。 -findstr / 1538802?noredirect = 1#comment2339443_1538802

そのスレッドを要約すると、バグは、入力が括弧で囲まれたコードブロック内のFINDSTRにパイプされると、インラインANSIエスケープカラーコードが後で実行されるコマンドで機能しなくなることです。インラインカラーコードの例は次のとおりですecho %magenta%Alert: Something bad happened%yellow%(マゼンタとイエローは、対応するANSIエスケープカラーコードとして.batファイルで以前に定義された変数です)。

私の最初の解決策は、FINDSTRの後に何もしないサブルーチンを呼び出すことでした。どういうわけか、呼び出しまたは戻りは、リセットする必要があるものは何でも「リセット」します。

後で、おそらくより効率的な別の解決策を発見しました。次の例のように、FINDSTRフレーズを括弧で echo success | ( FINDSTR /R success ) 囲みます。ネストされたコードブロック内にFINDSTRフレーズを配置すると、FINDSTRのカラーコードのバグが分離され、ネストされたものの外側に影響を与えないように見えます。ブロック。おそらく、この手法は、他の望ましくないFINDSTRの副作用も解決するでしょう

于 2020-04-09T13:53:12.467 に答える
-1

複数のディレクトリに関する/Dのヒント:検索文字列の前にディレクトリリストを配置します。これらはすべて機能します:

findstr /D:dir1;dir2 "searchString" *.*
findstr /D:"dir1;dir2" "searchString" *.*
findstr /D:"\path\dir1\;\path\dir2\" "searchString" *.*

予想どおり、ディレクトリを。で開始しない場合、パスは場所を基準にしています\"ディレクトリ名にスペースがない場合、パスをで囲むことはオプションです。エンディング\はオプションです。locationの出力には、指定したパスが含まれます。ディレクトリリストをで囲むかどうかに関係なく機能し"ます。

于 2015-01-22T20:11:26.393 に答える