Предисловие
Большая часть информации в этом ответе была собрана на основе экспериментов, проведенных на компьютере с Vista. Если прямо не указано иное, я не подтвердил, применима ли информация к другим версиям Windows.
Вывод FINDSTR
Документация никогда не объясняет вывод FINDSTR. Это намекает на то, что печатаются совпадающие строки, но не более того.
Формат соответствия строки выводится следующим образом:
Имя файла: LINENUMBER: lineOffset: текст
где
fileName: = Имя файла, содержащего совпадающую строку. Имя файла не печатается, если запрос был явно для одного файла, или при поиске вводимых по трубопроводу входов или перенаправленных входных данных. При печати fileName всегда будет содержать любую предоставленную информацию о пути. Дополнительная информация о пути будет добавлена, если используется эта/S
опция. Печатный путь всегда указывается относительно предоставленного пути или относительно текущего каталога, если он не указан.
Примечание. Префикса имени файла можно избежать при поиске в нескольких файлах с использованием нестандартных (и плохо документированных) подстановочных знаков <
и >
. Точные правила работы этих подстановочных знаков можно найти здесь . Наконец, вы можете посмотреть на этот пример того, как нестандартные символы подстановки работают с FINDSTR .
lineNumber: = Номер строки совпадающей строки, представленной в виде десятичного значения, где 1 представляет 1-ю строку ввода. Распечатывается, только если/N
указана опция.
lineOffset: = десятичное смещение байта начала совпадающей строки, где 0 представляет 1-й символ 1-й строки. Распечатывается, только если/O
указана опция. Это не смещение совпадения в строке. Это число байтов от начала файла до начала строки.
text = двоичное представление совпадающей строки, включая любые <CR> и / или <LF>. Ничего не осталось из двоичного вывода, так что этот пример, который соответствует всем строкам, даст точную двоичную копию исходного файла.
FINDSTR "^" FILE >FILE_COPY
Параметр / A задает цвет только для fileName :, lineNumber: и lineOffset: output. Текст соответствующей строки всегда выводится с текущим цветом консоли. Параметр / A действует только тогда, когда вывод отображается непосредственно на консоли. Параметр / A не действует, если выходные данные перенаправляются в файл или передаются по конвейеру. Смотрите описание 2018-08-18 в ответе Aacini для описания ошибочного поведения при перенаправлении вывода в CON.
Большинство контрольных символов и многие расширенные символы ASCII отображаются в виде точек в XP.
FINDSTR в XP отображает большинство непечатаемых контрольных символов из соответствующих строк в виде точек (точек) на экране. Следующие управляющие символы являются исключениями; они отображаются как сами: вкладка 0x09, перевод строки 0x0A, вертикальная вкладка 0x0B, подача формы 0x0C, возврат каретки 0x0D.
XP FINDSTR также преобразует ряд расширенных символов ASCII в точки. Расширенные символы ASCII, которые отображаются как точки в XP, такие же, как те, которые преобразуются при вводе в командной строке. См. Раздел «Ограничения символов для параметров командной строки - Расширенное преобразование ASCII» , далее в этом посте.
Управляющие символы и расширенный ASCII не преобразуются в точки в XP, если выходные данные передаются по конвейеру, перенаправляются в файл или в предложении FOR IN ().
Vista и Windows 7 всегда отображают все символы как сами по себе, а не как точки.
Коды возврата (ОШИБКА)
- 0 (успех)
- Найдено совпадение хотя бы в одной строке хотя бы одного файла.
- 1 (сбой)
- Не найдено совпадений ни в одной строке файла.
- Неверный цвет, указанный в
/A:xx
опции
- 2 (ошибка)
- Несовместимые параметры
/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
опции.
Имена файлов могут содержать пробелы и другие специальные символы. Большинство команд требуют, чтобы такие имена файлов были заключены в кавычки. Но /F:files.txt
опция FINDSTR требует, чтобы имена файлов в файле files.txt НЕ цитировались. Файл не будет найден, если имя указано в кавычках.
BUG - Short 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
будет найден правильно.
Не все короткие имена вызывают ошибку. Все случаи ошибочного поведения, которые я видел, включают расширение длиной более 3 символов с коротким 8.3 именем, которое начинается так же, как и обычное имя, которое не требует имени 8.3.
Ошибка была подтверждена на XP, Vista и Windows 7.
Непечатаемые символы и /P
вариант опция заставляет FINDSTR пропустить какой - либо файл , который содержит любой из следующих кодов байт десятичных:
0-7, 14-25, 27-31.
/P
Другими словами, /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 и Windows 7, если перенаправленный ввод не заканчивается.<LF>
Это неприятная «особенность» в XP и Windows 7. Если последний символ файла, используемого в качестве перенаправленного ввода, не заканчивается <LF>
, FINDSTR будет зависать бесконечно, как только он достигает конца перенаправленного файла.
Последняя строка данных Piped может игнорироваться, если она состоит из одного символа.
Если ввод передается по конвейеру, а последняя строка состоит из одного символа, за которым не следует <LF>
, то FINDSTR полностью игнорирует последнюю строку.
Пример - первая команда с одним символом и без <LF>
совпадения, но вторая команда с 2 символами работает нормально, как и третья команда с одним символом с завершающим символом новой строки.
> set /p "=x" <nul | findstr "^"
> set /p "=xx" <nul | findstr "^"
xx
> echo x| findstr "^"
x
Об этом сообщает пользователь DosTips Sponge Belly на новой ошибке findstr . Подтверждено на XP, Windows 7 и Windows 8. Еще не слышал о Vista. (У меня больше нет Vista для тестирования).
Синтаксис
опций Опция может иметь префикс либо либо, /
либо -
опции могут объединяться после одного /
или -
. Однако объединенный список параметров может содержать не более одного параметра с несколькими символами, например OFF или F:, и параметр из нескольких символов должен быть последним параметром в списке.
Ниже приведены все эквивалентные способы выражения регистрозависимого поиска без учета регистра для любой строки, которая содержит слова «привет» и «до свидания» в любом порядке.
/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, то результатом будет FINDSTR: Search string too long.
ошибка ERRORLEVEL 2.
При выполнении поиска по регулярному выражению максимальная длина строки поиска равна 254. Регулярное выражение с длиной от 255 до 511 приведет к FINDSTR: Out of memory
ошибке с ошибкой 2. Длина регулярного выражения> 511 приведет к FINDSTR: Search string too long.
ошибке.
В Windows XP длина строки поиска явно меньше. Ошибка Findstr: «Слишком длинная строка поиска»: как извлечь и сопоставить подстроку в цикле «for»?
Ограничение XP составляет 127 байтов для литерального и регулярного поиска.
Ограничения длины строки
Файлы, указанные в качестве аргумента командной строки или с помощью параметра / F: FILE, не имеют известного ограничения длины строки. Поиск был успешно выполнен для файла размером 128 МБ, который не содержал ни одного <LF>.
Данные по конвейеру и перенаправленный ввод ограничены 8191 байтами на строку. Этот лимит является «особенностью» FINDSTR. Это не присуще трубам или перенаправлению. FINDSTR, использующий перенаправленный ввод stdin или piped, никогда не будет соответствовать ни одной строке размером> = 8 Кбайт. Строки> = 8k генерируют сообщение об ошибке для stderr, но значение ERRORLEVEL равно 0, если строка поиска найдена хотя бы в одной строке хотя бы одного файла.
Тип поиска по умолчанию: Литерал против Регулярного выражения
/C:"string"
- по умолчанию это / L литерал. Явное объединение параметра / L с / C: «строка», безусловно, работает, но является избыточным.
"string argument"
- Значение по умолчанию зависит от содержимого самой первой строки поиска. (Помните, что <пробел> используется для разделения строк поиска.) Если первая строка поиска является допустимым регулярным выражением, которое содержит хотя бы один неэкранированный метасимвол, то все строки поиска обрабатываются как регулярные выражения. В противном случае все строки поиска рассматриваются как литералы. Например, "51.4 200"
будет обрабатываться как два регулярных выражения, поскольку первая строка содержит неэкранированную точку, тогда как "200 51.4"
будет рассматриваться как два литерала, поскольку первая строка не содержит метасимволов.
/G:file
- Значение по умолчанию зависит от содержимого первой непустой строки в файле. Если первая строка поиска является допустимым регулярным выражением, которое содержит хотя бы один неэкранированный метасимвол, то все строки поиска обрабатываются как регулярные выражения. В противном случае все строки поиска рассматриваются как литералы.
Рекомендация - всегда явно указывайте /L
опцию литерала или опцию /R
регулярного выражения при использовании "string argument"
или /G:file
.
ОШИБКА - Задание нескольких литеральных строк поиска может дать ненадежные результаты
В следующем простом примере FINDSTR не удается найти совпадение, даже если оно должно.
echo ffffaaa|findstr /l "ffffaaa faffaffddd"
Эта ошибка была подтверждена в Windows Server 2003, Windows XP, Vista и Windows 7.
Основываясь на экспериментах, FINDSTR может потерпеть неудачу, если выполнены все следующие условия:
- В поиске используются несколько литеральных строк поиска.
- Строки поиска имеют разную длину
- Короткая строка поиска имеет некоторое перекрытие с более длинной строкой поиска
- Поиск чувствителен к регистру (без
/I
опции)
При каждом сбое, которое я видел, всегда происходит сбой одной из коротких строк поиска.
Для получения дополнительной информации см. Почему этот пример FINDSTR с несколькими литеральными строками поиска не находит соответствия?
Кавычки и обратные слэши в аргументах командной строки
Примечание. Комментарии пользователя MC ND отражают действительно ужасно сложные правила для этого раздела. Есть 3 различных этапа анализа:
- Первый cmd.exe может потребовать экранировать некоторые кавычки как ^ "(на самом деле ничего общего с FINDSTR)
- Далее FINDSTR использует синтаксический анализатор аргументов C / C ++ до 2008 года , который имеет специальные правила для "и \".
- После завершения синтаксического анализа аргумента FINDSTR дополнительно обрабатывает \, сопровождаемый буквенно-цифровым символом, как литерал, но \ сопровождаемый не буквенно-цифровым символом, как escape-символ
Остальная часть этого выделенного раздела не на 100% правильна. Он может служить руководством для многих ситуаций, но приведенные выше правила необходимы для полного понимания.
Экранирование
кавычек в строках поиска командной строки Кавычки в строках поиска командной строки должны быть экранированы с помощью обратной косой черты
\"
. Это верно как для литеральных, так и для регулярных выражений поисковых строк. Эта информация была подтверждена на XP, Vista и Windows 7.
Примечание. Может также потребоваться экранирование кавычки для синтаксического анализатора CMD.EXE, но это не имеет ничего общего с FINDSTR. Например, для поиска одной цитаты вы можете использовать:
FINDSTR \^" file && echo found || echo not found
Экранирование обратной косой черты в строке поиска литералов командной строки Обратная косая черта в строке поиска
литералов обычно может быть представлена как
\
или как \\
. Они, как правило, эквивалентны. (В Vista могут быть необычные случаи, когда обратная косая черта всегда должна быть экранирована, но у меня больше нет машины Vista для тестирования) .
Но есть несколько особых случаев:
При поиске последовательных обратных слэшей все, кроме последнего, должны быть экранированы. Последний обратный слеш может быть при желании экранирован.
\\
может быть закодировано как \\\
или\\\\
\\\
может быть закодировано как \\\\\
или\\\\\\
Поиск одной или нескольких обратных косых черт перед тем, как цитата будет странной. Логика подсказывает, что нужно избегать кавычек, а каждую из ведущих обратных косых черт нужно избегать, но это не работает! Вместо этого каждый из ведущих обратных слэшей должен быть дважды экранирован, а кавычка экранирована как обычно:
\"
должен быть закодирован как \\\\\"
\\"
должен быть закодирован как \\\\\\\\\"
Как отмечалось ранее, для одной или нескольких экранированных кавычек может также потребоваться экранирование ^
для синтаксического анализатора CMD
Информация в этом разделе была подтверждена на XP и Windows 7.
Экранирование обратной косой черты в строке поиска регулярных выражений в командной строке
Только для Vista: обратная косая черта в регулярном выражении должна быть либо с двойным экранированием \\\\
, либо с одиночным экранированием в наборе классов символов, например
[\\]
XP и Windows 7: обратную косую черту в регулярном выражении всегда можно представить как [\\]
. Обычно это можно представить как \\
. Но это никогда не работает, если обратный слеш предшествует экранированной кавычке.
Одна или несколько обратных косых черт перед экранированной кавычкой должны быть либо экранированы дважды, либо кодированы как [\\]
\"
может быть закодировано как \\\\\"
или[\\]\"
\\"
может быть закодировано как \\\\\\\\\"
или [\\][\\]\"
или\\[\\]\"
Экранирование
кавычек и обратной косой черты в литеральных строках поиска / G: FILE Автономные кавычки и обратные косые черты в файле литеральных строк поиска, указанных в / G: file, не нужно экранировать, но они могут быть.
"
и \"
эквивалентны.
\
и \\
эквивалентны.
Если цель состоит в том, чтобы найти \\, то, по крайней мере, должен быть экранирован ведущий обратный слеш. Оба \\\
и \\\\
работают.
Если цель состоит в том, чтобы найти \ ", то, по крайней мере, должен быть экранирован ведущий обратный слеш. И то \\"
и другое \\\"
работает.
Экранирование кавычек и обратной косой черты в / G: строки поиска по регулярному выражению FILE
Это единственный случай, когда escape-последовательности работают, как и ожидалось, основываясь на документации. Цитата не является метасимволом регулярных выражений, поэтому ее не нужно экранировать (но можно). Обратная косая черта является метасимволом регулярных выражений, поэтому ее необходимо экранировать.
Пределы символов для параметров командной строки - Расширенное преобразование ASCII
Нулевой символ (0x00) не может появляться ни в одной строке командной строки. Любой другой однобайтовый символ может появиться в строке (0x01 - 0xFF). Однако FINDSTR преобразует многие расширенные символы ASCII, которые он находит в параметрах командной строки, в другие символы. Это оказывает серьезное влияние двумя способами:
1) Многие расширенные символы ASCII не будут совпадать, если они используются в качестве строки поиска в командной строке. Это ограничение одинаково для литеральных и регулярных поисков. Если строка поиска должна содержать расширенный ASCII, тогда /G:FILE
следует использовать эту опцию.
2) FINDSTR может не найти файл, если имя содержит расширенные символы ASCII и имя файла указано в командной строке. Если файл для поиска содержит расширенный ASCII в имени, тогда /F:FILE
вместо этого следует использовать эту опцию.
Вот полный список расширенных преобразований символов ASCII, которые FINDSTR выполняет в строках командной строки. Каждый символ представлен в виде десятичного значения байтового кода. Первый код представляет символ, указанный в командной строке, а второй код представляет символ, в который он преобразован. Обратите внимание - этот список был составлен на американском компьютере. Я не знаю, какое влияние на этот список могут оказать другие языки.
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
Символ nul (0x00) может появляться в файле, но он действует как терминатор строки C. Любые символы после нулевого символа обрабатываются как другая строка, как если бы они были в другой строке.
<CR>
И <LF>
символы рассматриваются как линейные терминаторы , которые завершаются строки, и не включаются в строку.
Все остальные однобайтовые символы полностью включены в строку.
Поиск файлов Unicode
FINDSTR не может правильно искать большинство Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32), потому что он не может искать нулевые байты, а Unicode обычно содержит много нулевых байтов.
Однако команда TYPE преобразует UTF-16LE с BOM в однобайтовый набор символов, поэтому такая команда будет работать с UTF-16LE с BOM.
type unicode.txt|findstr "search"
Обратите внимание, что кодовые точки Unicode, которые не поддерживаются вашей активной кодовой страницей, будут преобразованы в ?
символы.
Поиск в UTF-8 возможен, если строка поиска содержит только ASCII. Однако вывод на консоль любых многобайтовых символов UTF-8 будет неправильным. Но если вы перенаправите вывод в файл, то результат будет правильно закодирован UTF-8. Обратите внимание, что если файл UTF-8 содержит спецификацию, то эта спецификация будет рассматриваться как часть первой строки, что может привести к сбою в поиске, который соответствует началу строки.
Можно искать многобайтовые символы UTF-8, если поместить строку поиска в файл поиска в кодировке UTF-8 (без спецификации) и использовать параметр / G.
Конец строки
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 ниже ...
grep
которых является очень хорошо поняло и документированный :-) См stackoverflow.com/questions/2635740/... , например.