Следующий пример FINDSTR не может найти совпадение.
echo ffffaaa|findstr /l "ffffaaa faffaffddd"
Почему?
Следующий пример FINDSTR не может найти совпадение.
echo ffffaaa|findstr /l "ffffaaa faffaffddd"
Почему?
Очевидно, это долгое время ошибка FINDSTR. Я думаю, что это может быть искажающая ошибка, в зависимости от обстоятельств.
Я подтвердил, что команда не работает на двух разных компьютерах Vista, на компьютере с Windows 7 и на компьютере с XP. Я нашел эту ссылку findstr - broken???, которая сообщает, что аналогичный поиск не выполняется в Windows Server 2003, но он преуспевает в Windows 2000.
Я провел несколько экспериментов, и, кажется, все условия должны выполняться для потенциала отказа:
/I
)В каждой ошибке, которую я видел, она всегда является одной из коротких строк поиска, которая терпит неудачу.
Не имеет значения, как указаны строки поиска. Тот же самый дефектный результат достигается с помощью нескольких опций /C:"search"
, а также с опцией /G:file
.
Единственными тремя обходными решениями, которые я смог придумать, являются:
Используйте параметр /I
, если вам все равно. Очевидно, это может не соответствовать вашим потребностям.
Используйте параметр регулярного выражения /R
. Но если вы это сделаете, вам нужно убедиться, что вы избежите метасимволов в поиске, чтобы он соответствовал ожидаемому результатам литерала. Это может быть проблематично.
Если вы используете параметр /V
, используйте несколько команд FINDSTR с несколькими каналами с одной строкой поиска, а не с одним FINDSTR с несколькими поисками. Это также может быть проблемой, если у вас есть много строк поиска, для которых вы хотите использовать опцию /G:file
.
Я ненавижу эту ошибку!!!!
Примечание - см. Что представляют собой недокументированные функции и ограничения команды Windows FINDSTR? для полного списка особенностей FINDSTR.
Я не могу сказать, почему 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"
Предыдущие обратные косые черты просто выходят из каждого символа, включая те, которые имеют определенное значение в поиске регулярных выражений.
Символы <
и >
исключаются из экранирования, чтобы избежать конфликтов с границами слов, которые были выражены \<
и \>
при появлении в начале и в конце строки поиска, соответственно.
Так как регулярные выражения ограничены 254 символами для версий findstr
, прошедших после Windows XP (против буквенных строк, которые ограничены 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 для каждого встречающегося вышеупомянутого метасимвола, применяя для версий findstr
после Windows XP.
Вот еще один подход, в первую очередь, с использованием нечувствительного к регистру поиска с findstr
, а затем постфильтрация результата с помощью регистрозависимых сравнений:
echo ffffaaa|findstr /L /I "ffffaaa faffaffddd"|cmd /V /C set /P STR=""^&if @^^!STR^^[email protected]^^!STR:ffffaaa=ffffaaa^^! (echo(^^!STR^^!) else if @^^!STR^^[email protected]^^!STR:faffaffddd=faffaffddd^^! (echo(^^!STR^^!)
Восклицательные знаки с двойным экранированием гарантируют, что переменная STR
расширяется в явно вызванном экземпляре cmd
даже в случае, если задержка с задержкой включена в экземпляре хостинга cmd
.
Кстати, из-за того, что я называю дефектом дизайна, поиск с литеральными строками с использованием findstr
никогда не работает надежно, как только они содержат обратную косую черту, потому что они все еще могут быть использованы для выхода из метасимволов, хотя это и не обязательно; например, строка поиска \.
действительно соответствует .
; чтобы действительно соответствовать \.
буквально, вы должны указать строку поиска \\.
. Я не понимаю, почему мета-символы все еще распознаются при выполнении литералов, это не то, что я называю буквальным.