В следующем примере FINDSTR не удается найти совпадение.
echo ffffaaa|findstr /l "ffffaaa faffaffddd"
Почему?
В следующем примере FINDSTR не удается найти совпадение.
echo ffffaaa|findstr /l "ffffaaa faffaffddd"
Почему?
По-видимому, это давняя ошибка FINDSTR. Я думаю, что это может быть калечащей ошибкой, в зависимости от обстоятельств.
Я подтвердил, что команда не работает на двух разных машинах с Vista, на машине с Windows 7 и на машине с XP. Я нашел эту ссылку findstr - не работает ???, которая сообщает аналогичный поиск не работает в Windows Server 2003, но успешно выполняется в Windows 2000.
Я провел ряд экспериментов, и кажется, что все следующие условия должны быть выполнены для возможности отказа:
/I
)В каждом сбое, который я видел, всегда терпит неудачу одна из самых коротких строк поиска.
Неважно, как указаны строки поиска. Такой же ошибочный результат достигается при использовании нескольких опций /C:"search"
, а также при использовании опции /G:file
.
Единственные 3 обходных пути, которые я смог придумать, это:
Используйте опцию /I
, если вам не важен регистр. Очевидно, что это может не соответствовать вашим потребностям.
Используйте параметр регулярного выражения /R
. Но если вы это сделаете, вам нужно убедиться, что вы избегаете любых метасимволов в поиске, чтобы он соответствовал результату, ожидаемому от буквального поиска. Это также может быть проблематично.
Если вы используете параметр /V
, используйте несколько команд FINDSTR с одной строкой поиска вместо одной FINDSTR с несколькими поисками. Это также может быть проблемой, если у вас много строк поиска, для которых вы хотите использовать опцию /G:file
.
ненавижу этот баг!!!!
Примечание . См. какие недокументированные функции и ограничения Windows команда FINDSTR? для получения полного списка особенностей FINDSTR.
findstr
почти так же, как Skeet — гуру C# :-)
- person paxdiablo; 19.01.2012
Я не могу сказать, почему 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^^!==@^^!STR:ffffaaa=ffffaaa^^! (echo(^^!STR^^!) else if @^^!STR^^!==@^^!STR:faffaffddd=faffaffddd^^! (echo(^^!STR^^!)
Восклицательные знаки с двойным экранированием гарантируют, что переменная STR
расширяется в явно вызванном экземпляре cmd
, даже если отложенное раскрытие включено в хост-экземпляре cmd
.
Между прочим, из-за того, что я называю недостатком дизайна, поиск с литеральными строками с использованием findstr
никогда не работает надежно, если они содержат обратную косую черту, потому что они все еще могут быть использованы для экранирования следующих метасимволов, хотя это и не обязательно; например, строка поиска \.
фактически соответствует .
; чтобы действительно соответствовать \.
буквально, вы должны указать строку поиска \\.
. Я не понимаю, почему метасимволы все еще распознаются при буквальном поиске, это не то, что я называю буквальным.
ffffaaa
и все работает =D - person Anthony Miller   schedule 19.01.2012findstr
: с заданным переключателем/X
строка должна соответствовать точно для вывода; когда последняя строка в текстовом файле для поиска не заканчивается новой строкой,findstr
не возвращает ее (независимо от того, задано ли/L
или/R
, или поиск строке предшествует/C:
)... - person aschipfl   schedule 06.08.2015