10

次の FINDSTR の例では、一致が見つかりません。

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

なんで?

4

2 に答える 2

15

明らかに、これは長期にわたる FINDSTR のバグです。状況によっては致命的なバグになる可能性があると思います。

Windows 7 マシンと XP マシンの 2 つの異なる Vista マシンでコマンドが失敗することを確認しました。このfindstrを見つけました-壊れています??? 同様の検索を報告するリンクは、Windows Server 2003 では失敗しますが、Windows 2000 では成功します。

私は多くの実験を行いましたが、失敗の可能性については、次のすべての条件が満たされている必要があるようです。

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

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

検索文字列の指定方法は問いません。/C:"search"複数のオプションを使用しても、オプションを使用しても、同じ誤った結果が得られ/G:fileます。

私が思いついた唯一の3つの回避策は次のとおりです。

  • /I大文字と小文字を区別しない場合は、このオプションを使用してください。明らかに、これはニーズを満たしていない可能性があります。

  • /R正規表現オプションを使用します。ただし、そうする場合は、検索でメタ文字をエスケープして、リテラル検索で期待される結果と一致するようにする必要があります。これも問題になる可能性があります。

  • このオプションを使用している場合は/V、複数の検索で 1 つの FINDSTR を使用する代わりに、パイプで接続された複数の FINDSTR コマンドをそれぞれ 1 つの検索文字列で使用します。オプションを使用する検索文字列が多数ある場合、これも問題になる可能性があり/G:fileます。

私はこのバグが嫌いです!!!!

- 「Windows FINDSTR コマンドの文書化されていない機能と制限事項は何ですか? 」を参照してください。FINDSTRの特異性の包括的なリストについては。

于 2012-01-19T05:05:27.560 に答える
1

findstr複数のリテラル文字列で失敗する理由がわかりません。ただし、その厄介なバグを回避する方法を提供できます。

リテラル検索文字列がsearch_strings.txt...というテキスト ファイルにリストされているとします。

ffffaaa
faffaffddd

...、すべての文字の前にバックスラッシュを挿入することで、正規表現に変換できます。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
> "regular_expressions.txt" (
    for /F usebackq^ delims^=^ eol^= %%S in ("search_strings.txt") do (
        set "REGEX=" & set "STRING=%%S"
        for /F delims^=^ eol^= %%T in ('
            cmd /U /V /C echo(!STRING!^| find /V ""
        ') do (
            set "ESCCHR=\%%T"
            if "%%T"="<" (set "ESCCHR=%%T") else if "%%T"=">" (set "ESCCHR=%%T")
            setlocal EnableDelayedExpansion
            for /F "delims=" %%U in ("REGEX=!REGEX!!ESCCHR!") do (
                endlocal & set "%%U"
            )
        )
        setlocal EnableDelayedExpansion
        echo(!REGEX!
        endlocal
    )
)
endlocal

次に、変換されたファイルを使用しますregular_expressions.txt...:

\f\f\f\f\a\a\a
\f\a\f\f\a\f\f\d\d\d

...正規表現検索を行うには、複数の検索文字列でも問題なく機能するようです。

echo ffffaaa| findstr /R /G:"regular_expressions.txt"

先行するバックスラッシュは、正規表現検索で特定の意味を持つ文字を含むすべての文字を単純にエスケープします。

文字<とは、検索文字列の先頭と末尾にそれぞれ表示されると>で表現された単語境界との競合を避けるために、エスケープ対象から除外されます。\<\>

Windows XP より前のバージョンでは正規表現が 254 文字に制限されているためfindstr(511 文字に制限されているリテラル文字列とは対照的に)、元の検索文字列の長さは 127 文字に制限されています。逃走へ。


メタ文字., *, ^, $, [, ],のみ\をエスケープする別の方法を次に示し"ます。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_META=.*^$[]\"^" & rem (including `"`)
> "regular_expressions.txt" (
    for /F usebackq^ delims^=^ eol^= %%S in ("search_strings.txt") do (
        set "REGEX=" & set "STRING=%%S"
        for /F delims^=^ eol^= %%T in ('
            cmd /U /V /C echo(!STRING!^| find /V ""
        ') do (
            set "CHR=%%T"
            setlocal EnableDelayedExpansion
            if not "!_META!"=="!_META:*%%T=!" set "CHR=\!CHR!"
            for /F "delims=" %%U in ("REGEX=!REGEX!!CHR!") do (
                endlocal & set "%%U"
            )
        )
        setlocal EnableDelayedExpansion
        echo(!REGEX!
        endlocal
    )
)
endlocal

この方法の利点は、検索文字列の長さが 127 文字に制限されなくなり、254 文字から前述のメタ文字ごとに 1 を差し引いたものに制限され、findstrWindows XP より前のバージョンに適用されることです。


findstr最初に大文字と小文字を区別しない検索を使用し、次に大文字と小文字を区別する比較によって結果を事後フィルタリングする別の回避策を次に示します。

echo ffffaaa|findstr /L /I "ffffaaa faffaffddd"|cmd /V /C set /P STR=""^&if @^^!STR^^!==@^^!STR:ffffaaa=ffffaaa^^! (echo(^^!STR^^!) else if @^^!STR^^!==@^^!STR:faffaffddd=faffaffddd^^! (echo(^^!STR^^!)

二重エスケープされた感嘆符により、ホスティング インスタンスで遅延展開が有効になっている場合でもSTR、明示的に呼び出されたインスタンスで変数が展開されます。cmdcmd


ところで、私が設計上の欠陥と呼んでいるものにより、findstrバックスラッシュが含まれるとすぐにリテラル文字列を使用した検索が確実に機能することはありません。たとえば、検索文字列\.は実際に一致し.ます。文字どおりに完全に一致させるに\.は、検索文字列を指定する必要があります\\.。リテラル検索を行うときにメタ文字がまだ認識される理由がわかりません。それは私がリテラルと呼んでいるものではありません。

于 2017-06-04T22:02:24.327 に答える