簡體   English   中英

Windows FINDSTR 命令有哪些未記錄的功能和限制?

[英]What are the undocumented features and limitations of the Windows FINDSTR command?

Windows FINDSTR 命令的文檔非常糟糕。 通過FINDSTR /?可以獲得非常基本的命令行幫助。 , 或HELP FINDSTR ,但它嚴重不足。 https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr上有更多的在線文檔。

有許多 FINDSTR 功能和限制在文檔中甚至都沒有暗示。 如果沒有先驗知識和/或仔細的實驗​​,也無法預料到它們。

所以問題是 -未記錄的 FINDSTR 功能和限制是什么?

此問題的目的是提供許多未記錄功能的一站式存儲庫,以便:

A) 開發人員可以充分利用現有的功能。

B) 開發人員不會浪費時間去思考為什么某些東西在它看起來應該起作用的時候卻不起作用。

在回復之前,請確保您了解現有文檔。 如果信息被 HELP 覆蓋,那么它不屬於這里。

這也不是展示 FINDSTR 有趣用途的地方。 如果一個有邏輯的人可以根據文檔預測 FINDSTR 的特定用法的行為,那么它不屬於這里。

同樣,如果一個有邏輯的人可以根據任何現有答案中包含的信息來預測特定用法的行為,那么它也不屬於這里。

前言
此答案中的大部分信息是根據在 Vista 機器上運行的實驗收集的。 除非另有明確說明,否則我尚未確認該信息是否適用於其他 Windows 版本。

FINDSTR 輸出
該文檔從不費心解釋 FINDSTR 的輸出。 它暗示了打印匹配行的事實,但僅此而已。

匹配行輸出格式如下:

文件名:lineNumber:lineOffset:文本

在哪里

fileName: = 包含匹配行的文件的名稱。 如果請求明確地針對單個文件,或者搜索管道輸入或重定向輸入,則不會打印文件名。 打印時,文件名將始終包含提供的任何路徑信息。 如果使用/S選項,將添加其他路徑信息。 打印的路徑總是相對於提供的路徑,或者如果沒有提供,則相對於當前目錄。

注意 - 在搜索多個文件時,可以通過使用非標准(且文檔記錄不佳)通配符<>來避免文件名前綴。 可以在此處找到有關這些通配符如何工作的確切規則。 最后,您可以查看非標准通配符如何與 FINDSTR 一起使用的示例

lineNumber: = 匹配行的行號,以十進制值表示,1 表示輸入的第一行。 僅在指定/N選項時打印。

lineOffset: =匹配行開頭的十進制字節偏移量,0代表第一行的第一個字符。 僅在指定/O選項時打印。 不是該行內匹配的偏移量。 它是從文件開頭到行開頭的字節數。

text = 匹配行的二進制表示,包括任何 <CR> 和/或 <LF>。 二進制輸出中沒有遺漏任何內容,因此這個匹配所有行的示例將生成原始文件的精確二進制副本。

FINDSTR "^" FILE >FILE_COPY

/A 選項僅設置 fileName:、lineNumber: 和 lineOffset: 輸出的顏色。 匹配行的文本始終以當前控制台顏色輸出。 /A 選項僅在輸出直接顯示到控制台時才有效。 如果輸出被重定向到文件或管道,則 /A 選項無效。 有關將輸出重定向到 CON 時錯誤行為的描述,請參閱Aacini 的答案中的 2018-08-18 編輯

大多數控制字符和許多擴展的 ASCII 字符在 XP 上顯示為點
XP 上的 FINDSTR 將匹配行中的大多數不可打印控制字符顯示為屏幕上的點(句點)。 以下控制字符是例外; 它們顯示為自己:0x09 Tab、0x0A LineFeed、0x0B Vertical Tab、0x0C Form Feed、0x0D Carriage Return。

XP FINDSTR 還將許多擴展的 ASCII 字符轉換為點。 在 XP 上顯示為點的擴展 ASCII 字符與在命令行中提供時轉換的字符相同。 請參閱本文后面的“命令行參數的字符限制 - 擴展 ASCII 轉換”部分

如果輸出通過管道傳輸、重定向到文件或在 FOR IN() 子句中,則控制字符和擴展 ASCII 不會在 XP 上轉換為點。

Vista 和 Windows 7 始終將所有字符顯示為它們本身,而不是點。

返回代碼 (ERRORLEVEL)

  • 0(成功)
    • 在至少一個文件的至少一行中找到匹配項。
  • 1(失敗)
    • 在任何文件的任何行中都找不到匹配項。
    • /A:xx選項指定的顏色無效
  • 2(錯誤)
    • 指定了不兼容的選項/L/R
    • /A:/F:/C:/D:/G:后缺少參數
    • /F:file/G:file指定的文件未找到
  • 255(錯誤)

要搜索的數據源(根據 Windows 7 測試更新)
Findstr 只能從以下來源之一搜索數據:

  • 指定為參數和/或使用/F:file選項的文件名。

  • stdin 通過重定向findstr "searchString" <file

  • 來自管道type file | findstr "searchString" 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 中的文件名不能被引用。 如果名稱被引用,則不會找到該文件。

BUG - 短 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選項
/P選項使 FINDSTR 跳過包含以下任何十進制字節代碼的任何文件:
0-7、14-25、27-31。

換句話說, /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 不會改變重定向輸入。

如果重定向輸入不以<LF>結尾,FINDSTR 在 XP 和 Windows 7 上掛起
這是 XP 和 Windows 7 上的一個討厭的“功能”。如果用作重定向輸入的文件的最后一個字符不以<LF>結尾,那么一旦到達重定向文件的末尾,FINDSTR 將無限期掛起。

如果管道數據的最后一行由單個字符組成,則可能會被忽略
如果輸入是通過管道輸入的,並且最后一行由單個字符組成,並且后面沒有<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 來測試)。

選項語法
選項字母不區分大小寫,因此/i/I是等價的。

選項可以以/-為前綴,選項可以在單個/-之后連接。 但是,連接的選項列表最多可以包含一個多字符選項,例如 OFF 或 F:,並且多字符選項必須是列表中的最后一個選項。

以下是表達不區分大小寫的正則表達式搜索以任何順序包含“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"都是等價的。

如果搜索字符串以/-文字開頭,則必須使用/C/G選項。 感謝Stephan在評論中報告此問題(已刪除)。

如果使用了/c:string/g:file選項,那么如果文件名參數以-開頭,即使被引用,命令也會失敗。 這是因為沒有搜索字符串參數,因此文件名參數被視為一個選項。 最簡單的解決方法是在文件參數前面加上點反斜杠,如

findstr /c:"searchString" ".\-fileName.txt"

搜索字符串長度限制
在 Vista 上,單個搜索字符串的最大允許長度為 511 個字節。 如果任何搜索字符串超過 511,則結果為FINDSTR: Search string too long. ERRORLEVEL 2 的錯誤。

進行正則表達式搜索時,最大搜索字符串長度為 254。長度在 255 和 511 之間的正則表達式將導致FINDSTR: Out of memory錯誤,ERRORLEVEL 2。正則表達式長度 >511 將導致FINDSTR: Search string too long. 錯誤。

在 Windows XP 上,搜索字符串的長度顯然更短。 Findstr 錯誤:“搜索字符串太長”:如何在“for”循環中提取和匹配子字符串? 對於文字和正則表達式搜索,XP 限制為 127 個字節。

行長限制
指定為命令行參數或通過 /F:FILE 選項指定的文件沒有已知的行長度限制。 對不包含單個 <LF> 的 128MB 文件成功運行搜索。

管道數據和重定向輸入限制為每行 8191 個字節。 此限制是 FINDSTR 的“功能”。 它不是管道或重定向所固有的。 使用重定向標准輸入或管道輸入的 FINDSTR 永遠不會匹配 >=8k 字節的任何行。 Lines >= 8k 向 stderr 生成錯誤消息,但如果在至少一個文件的至少一行中找到搜索字符串,則 ERRORLEVEL 仍為 0。

默認搜索類型:文字與正則表達式
/C:"string" - 默認為 /L 文字。 將 /L 選項與 /C:"string" 顯式組合當然有效,但也是多余的。

"string argument" - 默認值取決於第一個搜索字符串的內容。 (請記住,<space> 用於分隔搜索字符串。)如果第一個搜索字符串是有效的正則表達式,並且至少包含一個未轉義的元字符,則所有搜索字符串都被視為正則表達式。 否則,所有搜索字符串都被視為文字。 例如, "51.4 200"將被視為兩個正則表達式,因為第一個字符串包含未轉義的點,而"200 51.4"將被視為兩個文字,因為第一個字符串不包含任何元字符。

/G:file - 默認值取決於文件中第一個非空行的內容。 如果第一個搜索字符串是包含至少一個未轉義元字符的有效正則表達式,則所有搜索字符串都被視為正則表達式。 否則,所有搜索字符串都被視為文字。

建議 - 使用"string argument"/G:file時,始終明確指定/L文字選項或/R正則表達式選項。

BUG - 指定多個文字搜索字符串可能會產生不可靠的結果

以下簡單的 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 使用2008 年之前的 MS C/C++ 參數解析器,它對 " 和 \
  • 參數解析器完成后,FINDSTR 還將后跟字母數字字符的 \ 視為文字,但將后跟非字母數字字符的 \ 視為轉義字符

此突出顯示部分的其余部分並非 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 正則表達式搜索字符串中的轉義引號和反斜杠
這是轉義序列根據文檔按預期工作的一種情況。 引號不是正則表達式元字符,因此不需要轉義(但可以轉義)。 反斜杠是一個正則表達式元字符,所以它必須被轉義。

命令行參數的字符限制 - 擴展的 ASCII 轉換
空字符 (0x00) 不能出現在命令行的任何字符串中。 任何其他單字節字符都可以出現在字符串中 (0x01 - 0xFF)。 但是,FINDSTR 會將它在命令行參數中找到的許多擴展 ASCII 字符轉換為其他字符。 這在兩個方面產生了重大影響:

  1. 如果在命令行上用作搜索字符串,許多擴展的 ASCII 字符將不會匹配它們自己。 對於文字和正則表達式搜索,此限制是相同的。 如果搜索字符串必須包含擴展的 ASCII,則應改用/G:FILE選項。

  2. 如果名稱包含擴展的 ASCII 字符並且在命令行上指定了文件名,則 FINDSTR 可能無法找到文件。 如果要搜索的文件在名稱中包含擴展的 ASCII,則應改用/F:FILE選項。

這是 FINDSTR 對命令行字符串執行的擴展 ASCII 字符轉換的完整列表。 每個字符都表示為十進制字節碼值。 第一個代碼表示命令行上提供的字符,第二個代碼表示它轉換成的字符。 注意 - 此列表是在美國機器上編譯的。 我不知道其他語言可能會對這個列表產生什么影響。

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 字符串終止符。 nul 字符之后的任何字符都被視為不同的字符串,就好像它們在另一行上一樣。

<CR><LF>字符被視為終止字符串的行終止符,並且不包含在字符串中。

所有其他單字節字符都完美地包含在字符串中。

搜索 Unicode 文件
FINDSTR 無法正確搜索大多數 Unicode(UTF-16、UTF-16LE、UTF-16BE、UTF-32),因為它無法搜索 nul 字節並且 Unicode 通常包含許多 nul 字節。

但是,TYPE 命令將帶有 BOM 的 UTF-16LE 轉換為單字節字符集,因此類似以下的命令將適用於帶有 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> 字符都必須顯式匹配。 如果找到多行匹配,則僅打印匹配的第一行。 FINDSTR 然后翻倍回到源代碼的第二行並重新開始搜索 - 有點像“前瞻”類型的功能。

假設 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 部分繼續......

答案從上面的第 1 部分繼續- 我遇到了 30,000 個字符的答案限制:-(

有限的正則表達式 (regex) 支持
FINDSTR 對正則表達式的支持非常有限。 如果 HELP 文檔中沒有,則不支持。

除此之外,支持的正則表達式以完全非標准的方式實現,因此結果可能與來自 grep 或 perl 之類的預期結果不同。

正則表達式行位置錨 ^ 和 $
^匹配輸入流的開頭以及緊跟在 <LF> 之后的任何位置。 由於 FINDSTR 也在 <LF> 之后換行,因此“^”的簡單正則表達式將始終匹配文件中的所有行,甚至是二進制文件。

$匹配緊接在 <CR> 之前的任何位置。 這意味着包含$的正則表達式搜索字符串將永遠不會匹配 Unix 樣式文本文件中的任何行,如果它缺少 <CR><LF> 的 EOL 標記,它也不會匹配 Windows 文本文件的最后一行。

注意 - 如前所述,通過管道和重定向到 FINDSTR 的輸入可能附加了不在源中的<CR><LF> 顯然,這會影響使用$的正則表達式搜索。

任何在^之前或$之后包含字符的搜索字符串將始終無法找到匹配項。

位置選項 /B /E /X
位置選項的工作方式與^$相同,除了它們也適用於文字搜索字符串。

/B 功能與正則表達式搜索字符串開頭的^相同。

/E 功能與正則表達式搜索字符串末尾的$相同。

/X 的功能與正則表達式搜索字符串的開頭和$都包含^相同。

正則表達式詞邊界
\<必須是正則表達式中的第一個術語。 如果正則表達式前面有任何其他字符,則該正則表達式將不匹配任何內容。 \<對應於輸入的最開頭、行的開頭(緊跟 <LF> 的位置)或緊跟任何“非單詞”字符的位置。 下一個字符不必是“單詞”字符。

\>必須是正則表達式中的最后一個術語。 如果后面有任何其他字符,正則表達式將不匹配任何內容。 \>對應於輸入的結尾、緊接在 <CR> 之前的位置或緊接在任何“非單詞”字符之前的位置。 前面的字符不必是“單詞”字符。

這是“非單詞”字符的完整列表,以十進制字節碼表示。 注意 - 此列表是在美國機器上編譯的。 我不知道其他語言可能會對這個列表產生什么影響。

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 用於建立正則表達式字符類范圍的排序規則排序。 字符表示為它們的十進制字節碼值。 如果使用代碼頁 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

正則表達式字符類術語限制和BUG
FINDSTR 不僅限制在正則表達式中最多 15 個字符類術語,而且無法正確處理超出限制的嘗試。 使用 16 個或更多字符類術語會導致交互式 Windows 彈出窗口顯示“查找字符串 (QGREP) 實用程序遇到問題並需要關閉。對於給您帶來的不便,我們深表歉意。” 消息文本因 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 和 Windows 7 上得到確認。

如果正則表達式搜索包含字節碼 0xFF(十進制 255),則它們將失敗(並且可能無限期掛起)
任何包含字節碼 0xFF(十進制 255)的正則表達式搜索都將失敗。 如果直接包含字節碼 0xFF,或者如果它隱式包含在字符類范圍內,則會失敗。 請記住,FINDSTR 字符類范圍不會根據字節碼值整理字符。 字符<0xFF>出現在<space><tab>字符之間的排序序列中相對較早。 因此,任何同時包含<space><tab>的字符類范圍都將失敗。

確切的行為會根據 Windows 版本略有不同。 如果包含 0xFF,Windows 7 將無限期掛起。 XP 沒有掛起,但總是找不到匹配項,並且偶爾會打印以下錯誤消息 - “進程試圖寫入不存在的管道。”

我無法再使用 Vista 機器,因此無法在 Vista 上進行測試。

正則表達式錯誤: . 並且[^anySet]可以匹配 End-Of-File
正則表達式. 元字符應該只匹配<CR><LF>以外的任何字符。 如果文件中的最后一行沒有被<CR><LF>終止,則存在一個允許它匹配 End-Of-File 的錯誤。 然而, . 將不匹配空文件。

例如,一個名為“test.txt”的文件包含單行x ,沒有終止<CR><LF> ,將匹配以下內容:

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

此錯誤已在 XP 和 Win7 上得到確認。

負字符集似乎也是如此。 [^abc]之類的內容將匹配 End-Of-File。 [abc]這樣的正字符集似乎可以正常工作。 我只在Win7上測試過。

當括號中包含多個命令並且有重定向文件到整個塊時:

< 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 不同; 不會將標准輸入文件指針從其當前位置移動。 例如,此代碼在搜索行之后插入新行:

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%"

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>

請注意,我已經在十六進制編輯器中驗證了所有行都以CRLF終止。 唯一的異常是由於copy的工作方式,文件以0x1A終止。 但是請注意,這種異常不會導致“小”文件出現問題

通過額外的測試,我確認了以下內容:

  • 對二進制文件使用帶有/b選項的copy可防止添加0x1A字符,並且findstr不會掛在 3GB 文件上。
  • 用不同的字符終止 3GB 文件也會導致findstr掛起。
  • 0x1A字符不會對“小”文件造成任何問題。 (對於其他終止字符也是如此。)
  • 0x1A之后添加CRLF可以解決問題。 LF本身可能就足夠了。)
  • 使用type將文件通過管道傳輸到findstr可以在不掛起的情況下工作。 (這可能是由於任一type的副作用或|插入額外的行尾。)
  • 使用重定向輸入<也會導致findstr掛起。 但這是意料之中的; 正如dbenham 的帖子中所解釋的那樣:“重定向的輸入必須以LF結尾”

當在文件名中使用短划線(-) 或短划線(-) 時,我想報告有關第一個答案中要搜索的數據源部分的錯誤。

更具體地說,如果您要使用第一個選項 -指定為參數的文件名,將找不到該文件。 只要您使用選項 2 - stdin via redirection或 3 - data stream from a pipe , 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. 通過重定向作為標准輸入
    我是帶有破折號的文件。

  3. 作為來自管道的數據流
    我是帶有破折號的文件。

帶有破折號的文件名:

  1. 作為論據
    FINDSTR:無法使用 - dash.txt 打開文件名

  2. 通過重定向作為標准輸入
    我是帶有破折號的文件。

  3. 作為來自管道的數據流
    我是帶有破折號的文件。

希望能幫助到你。

M。

findstr命令ErrorLevel (或退出代碼)設置為以下值之一,前提是沒有無效或不兼容的開關,並且沒有搜索字符串超過適用的長度限制:

  • 0當在所有指定文件的一行中至少遇到一個匹配項時;
  • 1否則;

在以下情況下,一行被認為包含匹配:

  • 沒有給出/V選項並且搜索表達式至少出現一次;
  • 給出了/V選項並且不出現搜索表達式;

這意味着/V選項也會更改返回的ErrorLevel ,但它不僅僅是還原它!

例如,當您有一個包含兩行的文件test.txt ,其中一行包含字符串text而另一行不包含時, findstr "text" "test.txt"findstr /V "text" "test.txt"返回的ErrorLevel0

基本上你可以說:如果findstr至少返回一行,則ErrorLevel設置為0 ,否則設置為1

請注意, /M選項不會影響ErrorLevel值,它只會改變輸出。

(為了完整起見: find命令的行為與/V選項和ErrorLevel完全相同; /C選項不影響ErrorLevel 。)

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% (其中洋紅色和黃色是之前在 .bat 文件中定義為對應的 ANSI 轉義顏色代碼的變量)。

我最初的解決方案是在 FINDSTR 之后調用一個無操作子例程。 不知何故,調用或返回“重置”了需要重置的任何內容。

后來我發現了另一種可能更有效的解決方案:將 FINDSTR 短語放在括號內,如下例所示: echo success | ( FINDSTR /R success ) echo success | ( FINDSTR /R success )將 FINDSTR 短語放在嵌套代碼塊中似乎可以隔離 FINDSTR 的顏色代碼錯誤,因此它不會影響嵌套塊之外的內容。 也許這種技術也將解決一些其他不受歡迎的 FINDSTR 副作用

多個目錄的 /D 提示:將您的目錄列表放在搜索字符串之前。 這些都有效:

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

正如預期的那樣,如果您不以\開頭目錄,則路徑是相對於位置的。 如果目錄名稱中沒有空格,則用"包圍路徑是可選的。結尾\是可選的。 location 的輸出將包括您提供的任何路徑。無論是否使用"包圍目錄列表,它都可以使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM